, // sort by less<string> on strId boost::multi_index::ordered_non_unique < boost::multi_index::tag< RsOrderIndex::ord_id >, BOOST_MULTI_INDEX_MEMBER( ord_record_item, std::string, strId ) , // sort by less<string> on strDescription boost::multi_index::ordered_non_unique < boost::multi_index::tag< RsOrderIndex::ord_desc >, BOOST_MULTI_INDEX_MEMBER( ord_record_item, std::string, strDescription ) , // sort by less<COleDateTime> on dtInService boost::multi_index::ordered_non_unique < boost::multi_index::tag< RsOrderIndex::ord_sevice >, BOOST_MULTI_INDEX_MEMBER( ord_record_item, COleDateTime,
I have a muti_index for a database. First I'll say, this will be so much better than my old way of running an SQL every time I wanted to change the order. Thanks. I never see a database bigger than some 1200 records, usually <200, so I'm not worried about memory bloat. So I've wrapped the multi_index in a class that will hide the boost includes from the rest of my app. I'll include the work below. I'd like to treat some kind of interface, like a generic iterator, depending on what order I have set. I would only use one iterator at a time. But the iterators are templated and have no base so that I can easily keep a set of iterators handy, say in a container, and then supply the appropriate iterator through an interface. In my class, RaOrderRecords, I'd something like: set.GetIt( ) set.IncIt( ) set.IsEndIt( ) etc. Or even overload so I could set++ And a member like SetOrder( [enum of new order] ) to have the internal iterator switched. I'm sure there is an elegant way to deal with this, but it escapes me. Thanks, Dan. ~~~~~ .hpp #pragma once // // ............................................................ namespace RsOrderIndex { struct ord_key{ }; struct ord_id{ }; struct ord_desc{ }; struct ord_sevice{ }; struct ord_remain{ }; struct ord_cat{ }; struct ord_group{ }; enum RecOrderIndex { ordNull, ordKey, ordId, ordDesc, ordService, ordRemain, ordCat, ordGroup, }; }; // ............................................................ class RaOrderRecords; struct ord_record_item { //properties RaOrderRecords* pParent; size_t absPos; //indexed properties long key; std::string strId; std::string strDescription; COleDateTime dtInService; long remaining; long catKey; long groupKey; //one and only constructor ord_record_item( RaOrderRecords *pInParent, long inKey, CString& inId, CString& inDesc, COleDateTime& indtIns, long inRemain, long inCatKey, long inGroupKey, size_t inPos ) :pParent( pInParent ) ,key( inKey ) ,strId( inId ) ,strDescription( inDesc ) ,dtInService( indtIns ) ,remaining( inRemain ) ,catKey( inCatKey ) ,groupKey( inGroupKey ) ,absPos( inPos ) { } //useful members size_t GetAbsPos( ) const { return absPos; } //indexing members bool operator < ( const ord_record_item& e ) const { return key < e.key; } unsigned long cat_pos( ) const; unsigned long group_pos( ) const; }; // ............................................................ #ifdef INCLUDE_ORDRECORD_BASE //to isolate boost headers typedef boost::multi_index::multi_index_container < ord_record_item, boost::multi_index::indexed_by < // sort by primary database key, ord_record_item comp boost::multi_index::ordered_unique < boost::multi_index::tag< RsOrderIndex::ord_key >, boost::multi_index::identity< ord_record_item > dtInService )
, // sort by less<COleDateTime> on remaining, Description boost::multi_index::ordered_non_unique < boost::multi_index::tag< RsOrderIndex::ord_remain >, boost::multi_index::composite_key < ord_record_item, BOOST_MULTI_INDEX_MEMBER( ord_record_item, long, remaining ), BOOST_MULTI_INDEX_MEMBER( ord_record_item, std::string, strDescription )
, // sort by category, description boost::multi_index::ordered_non_unique < boost::multi_index::tag< RsOrderIndex::ord_cat >, boost::multi_index::composite_key < ord_record_item, BOOST_MULTI_INDEX_CONST_MEM_FUN( ord_record_item, unsigned long, cat_pos ), BOOST_MULTI_INDEX_MEMBER( ord_record_item, std::string, strDescription )
, // sort by group, description boost::multi_index::ordered_non_unique < boost::multi_index::tag< RsOrderIndex::ord_group >, boost::multi_index::composite_key < ord_record_item, BOOST_MULTI_INDEX_CONST_MEM_FUN( ord_record_item, unsigned long, group_pos ), BOOST_MULTI_INDEX_MEMBER( ord_record_item, std::string, strDescription )
ord_record_set;
typedef ord_record_set::index< RsOrderIndex::ord_key >::type::iterator It_key_ord; typedef ord_record_set::index< RsOrderIndex::ord_id >::type::iterator It_id_ord; typedef ord_record_set::index< RsOrderIndex::ord_desc >::type::iterator It_desc_ord; typedef ord_record_set::index< RsOrderIndex::ord_sevice
::type::iterator It_service_ord; typedef ord_record_set::index< RsOrderIndex::ord_remain ::type::iterator It_remain_ord; typedef ord_record_set::index< RsOrderIndex::ord_cat >::type::iterator It_cat_ord; typedef ord_record_set::index< RsOrderIndex::ord_group >::type::iterator It_group_ord;
nth_index_iterator #else // INCLUDE_ORDRECORD_BASE //forward declared for general use, no multi record boost headers class ord_record_set; #endif // INCLUDE_ORDRECORD_BASE // ............................................................ class RaOrderRecords { ord_record_set* pOrder; RaCatGroupMap catSet; RaCatGroupMap groupSet; //RSKeyPosSet keyPosSet; public: RaOrderRecords( ); ~RaOrderRecords( ); bool ReadRecordSet( RaRecordset* pRS ); unsigned long GetCatPos( long inCatKey ) { RaCatGroupMapIt it= catSet.find( inCatKey ); if( it != catSet.end( ) ) return it->second.ordered; else return -1;//max unsigned } unsigned long GetGroupPos( long inGroupKey ) { RaCatGroupMapIt it= groupSet.find( inGroupKey ); if( it != groupSet.end( ) ) return it->second.ordered; else return -1;//max unsigned } #ifdef _DEBUG void Dump( RsOrderIndex::RecOrderIndex index ); #else void Dump( RsOrderIndex::RecOrderIndex index ) { } #endif }; ~~~~~~.cpp #include "stdafx.h" #if !defined(NDEBUG) #include <boost/multi_index/safe_mode_errors.hpp> #define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING #define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE #endif #include <boost/multi_index_container.hpp> #include <boost/multi_index/ordered_index.hpp> #include <boost/multi_index/identity.hpp> #include <boost/multi_index/member.hpp> #include <boost/multi_index/mem_fun.hpp> #include <boost/multi_index/composite_key.hpp> #include "records.h" #define INCLUDE_ORDRECORD_BASE #include "RecordsOrd.hpp" // ......................................................... using namespace boost::multi_index; using namespace RsOrderIndex; unsigned long ord_record_item::cat_pos( ) const { return pParent->GetCatPos( catKey ); } unsigned long ord_record_item::group_pos( ) const { return pParent->GetGroupPos( groupKey ); } RaOrderRecords::RaOrderRecords( ) { pOrder= new ord_record_set; } RaOrderRecords::~RaOrderRecords( ) { delete pOrder; } bool RaOrderRecords::ReadRecordSet( RaRecordset* pRS ) { pOrder->clear( ); LoadCategories( catSet ); LoadGroups( groupSet ); COleDateTime dtNo( 10000.0 );// TODO !!!! try { int i= 1; for( pRS->MoveFirst( ); ! pRS->IsEOF( ); pRS->MoveNext( ) ) { pOrder->insert( ord_record_item( this, pRS->ds_id, pRS->ds_number, pRS->ds_description, pRS->IsFieldNull( &pRS->ds_inService ) ? dtNo : pRS->ds_inService, pRS->GetRemaining( ), pRS->ds_catKey, pRS->ds_groupKey, i ) ); // keyPosSet.SetKeyPos( pRS->ds_id, i++ ); } } catch( CDBException* e ) { e->Delete( ); return false; } return true; } #ifdef _DEBUG void RaOrderRecords::Dump( RecOrderIndex index ) { std::string strT; strT.c_str( ); It_cat_ord it= pOrder->get< ord_cat >( ).begin( ); for( int i= 1; it != pOrder->get< ord_cat >( ).end( ); ++it, ++i ) { CString strT; RaCatGroupMapIt cat= catSet.find( it->catKey ); if( cat != catSet.end( ) ) strT= cat->second.title; else strT= _T("(null)"); TRACE( "%3.0d %s---%s\n", i, strT, it->strDescription.c_str( ) ); } //It_service_ord sit= pOrder->get< ord_sevice >( ).begin( ); //for( ; sit != pOrder->get< ord_sevice >( ).end( ); ++sit ) // TRACE( "%s---%s\n", sit->strDescription.c_str( ), sit->dtInService.Format( _T("%m/%d/%y") ) ); } #endif //_DEBUG