boost multi-index container find method.

Hello Joaquin, I have a class like below that uses mult-index container's find method. I have a record pattern as below initially: Idx : 100 Flag : 5 Idx : 200 Flag : 5 Idx : 300 Flag : 5 Idx : 400 Flag : 5 I modify the flag for index 100 to 6 & take a dump, the change is OK Idx : 100 Flag : 6 Idx : 200 Flag : 5 Idx : 300 Flag : 5 Idx : 400 Flag : 5 I modify the flag for 100 back to 5 and take a dump, which is also fine. Idx : 100 Flag : 5 Idx : 200 Flag : 5 Idx : 300 Flag : 5 Idx : 400 Flag : 5 Now I do a find based on flag value set to 5 I get the results as below: Idx : 200 flag : 5 While find functionally is correct in picking up the correct data, but I am wondering why it doesnt pick the first record (100) which has the flag value set to 5? am I missing something in the indexing definition in the container itself? Thanks /R ========================= using namespace std; #include <boost/lambda/lambda.hpp> #include <boost/multi_index_container.hpp> #include <boost/multi_index/ordered_index.hpp> #include <boost/multi_index/member.hpp> #include <iostream> #include <iterator> #include <iostream> #include <string> struct Token { unsigned long mIdx; unsigned char mflag; public: Token(unsigned long pIdx, unsigned char pflag): mIdx(pIdx), mflag(pflag){} void Update(unsigned char pflag) { mflag = pflag; } ~Token() { mIdx = 0; mflag = 1; } }; struct mIdx{}; struct mflag{}; using namespace boost::multi_index; namespace ll = boost::lambda; typedef multi_index_container< Token, indexed_by< ordered_unique< tag <mIdx>, BOOST_MULTI_INDEX_MEMBER(Token,unsigned long,mIdx)>, ordered_non_unique< tag <mflag>, BOOST_MULTI_INDEX_MEMBER(Token,unsigned char,mflag)> >
tToken;
class TokenMaster { tToken TokenContainer; public: unsigned long getByFlag(unsigned long useFlag); bool modify(unsigned long idx, unsigned char flag); bool insert(unsigned long, unsigned char); void dump(); }; unsigned long TokenMaster::getByFlag(unsigned long useFlag) { typedef tToken::index<mflag>::type itflag; itflag& mflag_index = TokenContainer.get<mflag>(); tToken::index_iterator<mflag>::type flagit = mflag_index.find(useFlag); if (flagit == mflag_index.end()) { return 0; } printf("Idx : %d flag : %d\n", flagit->mIdx, flagit->mflag); return flagit->mIdx; } bool TokenMaster::modify(unsigned long idx, unsigned char flag) { tToken::iterator itIp=TokenContainer.find(idx); if (itIp == TokenContainer.end()) return false; return TokenContainer.modify(itIp,(&ll::_1)->*&Token::mflag=flag); } bool TokenMaster::insert(unsigned long idx, unsigned char flag) { tToken::iterator it; bool secres; std::pair<tToken::iterator, bool> result = TokenContainer.insert(Token(idx, flag)); it = result.first; secres = result.second; if (secres) return true; else return false; } void TokenMaster::dump() { unsigned long count = 0; printf("\n\n List of indexes\n"); for (tToken::iterator it = TokenContainer.begin(), it_end=TokenContainer.end(); it != it_end; ++it, count++) { printf("Idx : %d Flag : %d\n", it->mIdx, it->mflag); } printf("\n"); } main() { TokenMaster T1; T1.insert(100, 5); T1.insert(200, 5); T1.insert(300, 5); T1.insert(400, 5); T1.dump(); printf("Modifiying 100 to 6\n"); T1.modify(100, 6); T1.dump(); printf("Modifiying 100 back to 5\n"); T1.modify(100, 5); T1.dump(); printf("\n\nGet by flag \n"); T1.getByFlag(5); } ==========================

Idx : 200 flag : 5
While find functionally is correct in picking up the correct data, but I am wondering why it doesnt pick the first record (100) which has the flag value set to 5? am I missing something in the indexing definition in the container itself?
You have 2 separate, unrelated indices, so (100, 5) should be the 1st entry on the 2nd index? It doesn't sort by "idx" field. Probably you want to make the second index "composite" (flag, idx) - then you'll get the desired functionality.

Sorry not necessarily, that was incorrect. On Thu, Sep 17, 2009 at 12:19 PM, Igor R <boost.lists@gmail.com> wrote:
typo:
so (100, 5) should be the 1st entry on the 2nd index
so *why* (100, 5) should be the 1st entry on the 2nd index _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Thank you Igor. On Thu, Sep 17, 2009 at 12:18 PM, Igor R <boost.lists@gmail.com> wrote:
Idx : 200 flag : 5
While find functionally is correct in picking up the correct data, but I am wondering why it doesnt pick the first record (100) which has the flag value set to 5? am I missing something in the indexing definition in the container itself?
You have 2 separate, unrelated indices, so (100, 5) should be the 1st entry on the 2nd index? It doesn't sort by "idx" field. Probably you want to make the second index "composite" (flag, idx) - then you'll get the desired functionality. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Ramesh <rramesh1 <at> gmail.com> writes:
Hello Joaquin,
Hi Ramesh,
I have a class like below that uses mult-index container's find method. I have a record pattern as below initially:
Idx : 100 Flag : 5 Idx : 200 Flag : 5 Idx : 300 Flag : 5 Idx : 400 Flag : 5
[...]
Idx : 200 flag : 5
While find functionally is correct in picking up the correct data, but I am wondering why it doesnt pick the first record (100) which has the flag value set to 5?
find() returns an element with the searched key in case there is one, but note that no guarantee is made about which element is returned when there are several to choose from (in case you're curious: ordered indices are internally implemented as rd-trees, and find simply returns the first element found when traversing the tree topdown). Even if you use lower_bound() to find the first element of the range, there is no guarantee that (100,5) appears the first on the flag-based index. You can follow Igor's advice on using a composite key here. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

Thank you very much. On Thu, Sep 17, 2009 at 12:25 PM, Joaquin M Lopez Munoz <joaquin@tid.es> wrote:
Ramesh <rramesh1 <at> gmail.com> writes:
Hello Joaquin,
Hi Ramesh,
I have a class like below that uses mult-index container's find method. I have a record pattern as below initially:
Idx : 100 Flag : 5 Idx : 200 Flag : 5 Idx : 300 Flag : 5 Idx : 400 Flag : 5
[...]
Idx : 200 flag : 5
While find functionally is correct in picking up the correct data, but I am wondering why it doesnt pick the first record (100) which has the flag value set to 5?
find() returns an element with the searched key in case there is one, but note that no guarantee is made about which element is returned when there are several to choose from (in case you're curious: ordered indices are internally implemented as rd-trees, and find simply returns the first element found when traversing the tree topdown).
Even if you use lower_bound() to find the first element of the range, there is no guarantee that (100,5) appears the first on the flag-based index. You can follow Igor's advice on using a composite key here.
Joaquín M López Muñoz Telefónica, Investigación y Desarrollo
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (3)
-
Igor R
-
Joaquin M Lopez Munoz
-
Ramesh