multi-index-container with nested templates => problem getting iterator on 2nd index.

Hi, I'm really stuck on this one, so I'm hoping someone can lend me a hand. Basically, I'm defining a templated multi-index-container to hold one piece of data along with two indexes to that data. Next, I'm wrapping that in another templated class that will handle concurrent access to that structure. My problem is that I'm having trouble figuring out how to define a type that will give me an interator on the 2nd index of the multi-index-container ("bimimapIterator2" below). I'm basing this on the Boost multi-index-container example here: http://www.boost.org/doc/libs/1_39_0/libs/multi_index/example/bimap.cpp Here's what I have... //******************************************************************** // multi-index-container //******************************************************************** struct index1{}; struct index2{}; template<typename Key1,typename Key2, typename Data> struct bimultimap { typedef boost::tuple<Key1,Key2,Data> value_type; typedef boost::multi_index_container< value_type, indexed_by< ordered_non_unique< tag<index1>,member<value_type,Key1,&value_type::first> >, ordered_non_unique< tag<index2>,member<value_type,Key2,&value_type::second> > >
bimimap;
}; //******************************************************************** // concurrent access class. //******************************************************************** template<typename Key1, typename Key2, typename Data> class concurrent_bimultimap { private: typename bimultimap<Key1, Key2, Data>::bimimap the_bimultimap; mutable boost::mutex the_mutex; boost::condition_variable the_condition_variable; public: typedef typename bimultimap<Key1,Key2,Data>::bimimap bimimapType; typedef typename bimultimap<Key1,Key2,Data>::bimimap::iterator bimimapIterator; typedef typename bimultimap<Key1,Key2,Data>::bimimap::index<index2>::type::iterator bimimapIterator2; void insert(Key1 const& key1, Key2 const& key2, Data const& data) { boost::mutex::scoped_lock lock(the_mutex); the_bimultimap.insert( bimultimap<Key1,Key2,Data>::bimimap::value_type(key1,key2,data) ); lock.unlock(); // Note: because we unlock above and notify below, we can starve the "pop" thread for short durations in burst situations. That's ok so far. the_condition_variable.notify_one(); } bool findKey1(Key1& key1, Data& data) { boost::mutex::scoped_lock lock(the_mutex); bimimapIterator itFindIt = the_bimultimap.find(key1); if (itFindIt != the_bimultimap.end()) { data = itFindIt->third; return true; } else return false; } bool findKey2(Key2& key2, Data& data) { boost::mutex::scoped_lock lock(the_mutex); bimimapIterator2 itFindIt = the_bimultimap.get<index2>().find(key2); if (itFindIt != the_bimultimap.get<index2>().end()) { data = itFindIt->third; return true; } else return false; } ..... there's more but this gives the essence of the problem .... };

Hi Joh, JohnQ <jqs <at> jqs.net> writes:
Hi, I'm really stuck on this one, so I'm hoping someone can lend me a hand. Basically, I'm defining a templated multi-index-container to hold one piece of data along with two indexes to that data. Next, I'm wrapping that in another templated class that will handle concurrent access to that structure.
My problem is that I'm having trouble figuring out how to define a type that will give me an interator on the 2nd index of the multi-index-container ("bimimapIterator2" below).
[...]
typedef boost::multi_index_container< value_type, indexed_by< ordered_non_unique< tag<index1>,member<value_type,Key1,&value_type::first> >,
This cannot possibly work, as value_type does not have a member called first (you're using a tuple, not an std::pair). Anyway, the problem does not lie here. [...]
typedef typename bimultimap<Key1,Key2,Data>:: bimimap::index<index2>::type::iterator bimimapIterator2;
You need a disambiguating template keyword: typedef typename bimultimap<Key1,Key2,Data>:: bimimap::template index<index2>::type::iterator bimimapIterator2; Hope this helps. Thanks for using Boost.MultiIndex, Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

typedef boost::multi_index_container< value_type, indexed_by< ordered_non_unique< tag<index1>,member<value_type,Key1,&value_type::first> >,
This cannot possibly work, as value_type does not have a member called first (you're using a tuple, not an std::pair). Anyway, the problem does not lie here.
Yes, I've been ignoring this while I figured out the iterator... it's leftover from the example and I just named things first,second,third while I get the rest figured out. What I did instead was use the structure below... I didn't want to mess with stuff like tuple_element<N>::template get<RET>(x) (or whatever the correct type-independent tuple-element accessor would be) becuase I'm really not that familiar with this sort of meta programming... this seems like it will work but if you're familiar with a better way, I'd love to hear about it. template <typename T1, typename T2, typename T3> struct bimultimap_triple { typedef T1 first_type; typedef T2 second_type; typedef T3 third_type; bimultimap_triple():first(T1()),second(T2()),third(T3()){} bimultimap_triple(const T1& f,const T2& s, const T3& t):first(f),second(s),third(t){} T1 first; T2 second; T3 third; };
[...]
typedef typename bimultimap<Key1,Key2,Data>:: bimimap::index<index2>::type::iterator bimimapIterator2;
You need a disambiguating template keyword:
typedef typename bimultimap<Key1,Key2,Data>:: bimimap::template index<index2>::type::iterator bimimapIterator2;
That compiles (BIG THANK YOU). Next step is for me to figure out what this actually does. :) Can you give me some background (or point me to the correct reading material) on why the "template" qualifier is needed and what effect that has? I need to learn more about this...
Hope this helps. Thanks for using Boost.MultiIndex,
Definitely helped. Thanks. :)
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

JohnQ escribió:
> typedef boost::multi_index_container< > value_type, > indexed_by< > ordered_non_unique< > tag<index1>,member<value_type,Key1,&value_type::first> >,
This cannot possibly work, as value_type does not have a member called first (you're using a tuple, not an std::pair). Anyway, the problem does not lie here.
Yes, I've been ignoring this while I figured out the iterator... it's leftover from the example and I just named things first,second,third while I get the rest figured out. What I did instead was use the structure below... I didn't want to mess with stuff like tuple_element<N>::template get<RET>(x) (or whatever the correct type-independent tuple-element accessor would be) becuase I'm really not that familiar with this sort of meta programming... this seems like it will work but if you're familiar with a better way, I'd love to hear about it.
You have to define a custom key extractor to work with tuples: for an example, look for "tuple_member_extractor" at http://lists.boost.org/boost-users/2005/12/16088.php [...]
> typedef typename bimultimap<Key1,Key2,Data>:: > bimimap::index<index2>::type::iterator bimimapIterator2;
You need a disambiguating template keyword:
typedef typename bimultimap<Key1,Key2,Data>:: bimimap::template index<index2>::type::iterator bimimapIterator2;
That compiles (BIG THANK YOU). Next step is for me to figure out what this actually does. :) Can you give me some background (or point me to the correct reading material) on why the "template" qualifier is needed and what effect that has? I need to learn more about this...
The need for diambiguating "template"s is related to the usage of "typename" in expressions like "typedef typename bimultimap..." that appear in so-called dependent contexts. Some further explanations at http://www.comeaucomputing.com/techtalk/templates/#templateprefix Joaquín M López Muñoz Telefónica, Investigación y Desarrollo
participants (3)
-
Joaquin M Lopez Munoz
-
joaquin@tid.es
-
JohnQ