compile problem using multi_index_container

Hello, I've encountered a problem compiling code that uses boost multi_index_container. I'm using both Microsoft Visual Studio 2005 and Apple's gcc 4.0.1. Visual Studio was very picky about how I used namespaces. I finally got it working with the code below. The key to success was the 'using namespace boost::multi_index' line. If I attempted to prefix the members directly, eg. typedef typename boost::multi_index::nth_index_const_iterator<0>::type left_const_iterator; or namespace mi=boost::multi_index; typedef typename mi::nth_index_const_iterator<0>::type left_const_iterator; it would fail to compile. However, when I attempt to compile the same code on Mac OS X using gcc 4.0.1 I get the following errors. Does anyone know why? src.cpp:98:error: wrong number of template arguments (1, should be 2) /boost/boost/multi_index_container_fwd.hpp:46: error: provided for 'template<class MultiIndexContainer, int N> struct boost::multi_index::nth_index_const_iterator' src.cpp:98: error: expected ';' before 'left_const_iterator' src.cpp:99: error: wrong number of template arguments (1, should be 2) /boost/boost/multi_index_container_fwd.hpp:46: error: provided for 'template<class MultiIndexContainer, int N> struct boost::multi_index::nth_index_const_iterator' src.cpp:99: error: expected ';' before 'right_const_iterator' -----code---- using namespace boost::multi_index; 88 template<class A, class B=String> 89 class SimpleBiMap : public multi_index_container< 90 pair<A,B>, 91 indexed_by< 92 ordered_unique<member<pair<A,B>, A, &pair<A,B>::first> >, 93 ordered_unique<member<pair<A,B>, B, &pair<A,B>::second> > 94 > > 95 { 96 public: 97 typedef pair<A,B> mytype; 98 typedef typename nth_index_const_iterator<0>::type left_const_iterator; 99 typedef typename nth_index_const_iterator<1>::type right_const_iterator; 100 101 SimpleBiMap(const mytype init[], int N) { 102 for (int i=0; i<N; i++) { 103 insert(init[i]); 104 } 105 } 106 107 left_const_iterator find(const A &key) const { return get<0>().find(key); } 108 right_const_iterator find(const B &key) const { return get<1>().find(key); } 109 110 left_const_iterator left_end() const { return get<0>().end(); } 111 right_const_iterator right_end() const { return get<1>().end(); } 112 113 const B &operator[](const A &key) const { return get<0>().find(key)->second; } 114 const A &operator[](const B &key) const { return get<1>().find(key)->first; } 115 }; ---code--- Thank you, Dwight Kelly Apago, Inc.

Dwight Kelly ha escrito:
Hello,
I've encountered a problem compiling code that uses boost multi_index_container. I'm using both Microsoft Visual Studio 2005 and Apple's gcc 4.0.1. Visual Studio was very picky about how I used namespaces. I finally got it working with the code below.
The key to success was the 'using namespace boost::multi_index' line. If I attempted to prefix the members directly, eg.
typedef typename boost::multi_index::nth_index_const_iterator<0>::type left_const_iterator;
or
namespace mi=boost::multi_index; typedef typename mi::nth_index_const_iterator<0>::type left_const_iterator;
it would fail to compile.
However, when I attempt to compile the same code on Mac OS X using gcc 4.0.1 I get the following errors. Does anyone know why?
[...] Hello Dwight, For the sake of reference, let me reproduce the relevant part of your code: using namespace boost::multi_index; template<class A, class B=String> class SimpleBiMap : public multi_index_container< pair<A,B>, indexed_by< ordered_unique<member<pair<A,B>, A, &pair<A,B>::first> >, ordered_unique<member<pair<A,B>, B, &pair<A,B>::second> > > > { public: typedef pair<A,B> mytype; typedef typename nth_index_const_iterator<0>::type left_const_iterator; typedef typename nth_index_const_iterator<1>::type right_const_iterator; ... First of all, there are two variants of nth_index_const_iterator: * a global boost::multi_index::nth_index_const_iterator<MultiIndexContainer,N> * a nested MultiIndexContainer::nth_index_const_iterator<N> where the former accepts two arguments (the container type and the index number) while the latter, being nested into the container itself, only asks for the index number. Your code clearly means to use the second variant, but it does so in an incorrect fashion: you are expecting that nth_index_const_iterator is "found" inside the base class of SimpleBiMap, much as this *non-template* legal code does: struct base { typedef int type; }; struct derived: public base { typedef type type2; }; Unfortunately, this idiom does not extend to templatized code, even if you qualify the definition with a "typename" keyword. A little more info on this can be found at http://www.comeaucomputing.com/techtalk/templates/#whymembernotfound So, you need to qualify the typedefs as follows: typedef multi_index_container< mytype, indexed_by< ordered_unique<member<mytype, A, &mytype::first> >, ordered_unique<member<mytype, A, &mytype::second> > >
super; typedef typename super::template nth_index_const_iterator<0>::type left_const_iterator; typedef typename super::template nth_index_const_iterator<1>::type right_const_iterator;
As you see, you have to repeat the full type you are deriving from, which in the case of long multi_index_container instantiations is a bit annoying. Incidentally, you were missing some "template" keywords before nth_index_const_iterator, some compilers are lenient about this though. As for why your code compiled in VS, I'd say it was sheer luck: the code as you wrote it is illegal and VS should have complained. Looks like the using directive leads the compiler into taking the definitions of left_const_iterator and right_const_iterator as referring to the global variant of nth_index_const_iterator (which they are not) but on some further stage of the compilation the right variant ends up being chosen. Hope this helps, Joaquín M López Muñoz Telefónica, Investigación y Desarrollo
participants (2)
-
Dwight Kelly
-
Joaquín Mª López Muñoz