multi_index and base class

Hi, I'm trying to store these classes in a multi_index: struct Foo { int a; }; struct Bar :Foo { }; typedef multi_index_container< Bar, indexed_by< ordered_unique< member<Foo, int, &Bar::a> > >
Bar_container;
Notice I have to use "Foo" in the "member<" line. However, even with this, when trying to do a search: Bar_container bar_container; int function() { Bar_container::nth_index<0>::type& a_index = bar_container.get<0>(); Bar_container::nth_index<0>::type::iterator i = a_index.find(5); if (i != a_index.end()) return -1; return 0; } I get this: /usr/include/boost/multi_index/member.hpp: In member function 'Type& boost::multi_index::detail::non_const_member_base<Class, Type, PtrToMember>::operator()(const ChainedPtr&) const [with ChainedPtr = Bar, Class = Foo, Type = int, Type Class::* PtrToMember = &Foo::a]': /usr/include/boost/multi_index/detail/ord_index_ops.hpp:65: instantiated from 'Node* boost::multi_index::detail::ordered_index_find(Node*, const KeyFromValue&, const CompatibleKey&, const CompatibleCompare&) [with Node = boost::multi_index::detail::ordered_index_node<boost::multi_index::detail::i ndex_node_base<Bar>
, KeyFromValue = boost::multi_index::member<Foo, int, &Foo::a>, CompatibleKey = int, CompatibleCompare = std::less<int>]' /usr/include/boost/multi_index/ordered_index.hpp:376: instantiated from 'boost::multi_index::detail::index_iterator<boost::multi_index::detail::orde red_index_node<typename SuperMeta::type::node_type> > boost::multi_index::detail::ordered_index<KeyFromValue, Compare, SuperMeta, TagList, Category>::find(const CompatibleKey&) const [with CompatibleKey = int, KeyFromValue = boost::multi_index::member<Foo, int, &Foo::a>, Compare = std::less<int>, SuperMeta = boost::multi_index::detail::nth_layer<1, Bar, boost::multi_index::indexed_by<boost::multi_index::ordered_unique<boost::mul ti_index::member<Foo, int, &Foo::a>, mpl_::na, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::allocator<Bar> >, TagList = boost::mpl::vector0<mpl_::na>, Category = boost::multi_index::detail::ordered_unique_tag]' multitest2.cc:55: instantiated from here /usr/include/boost/multi_index/member.hpp:84: error: no match for 'operator*' in '*x'
I've tried a few alternatives such as providing a custom compare function but I always get this error. It seems to have something to do with the fact that the key is in the base class. If I move the key to the derived class (and change the "member<" line), it works fine. Surely there's a way to do this. Anyone know how ? Using gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21) and libboost 1.33.1. Thanks ___________________________________________________________ New Yahoo! Mail is the ultimate force in competitive emailing. Find out more at the Yahoo! Mail Championships. Plus: play games and win prizes. http://uk.rd.yahoo.com/evt=44106/*http://mail.yahoo.net/uk

Hello Andrej, Andrej van der Zee ha escrito:
Hi,
I'm trying to store these classes in a multi_index:
struct Foo { int a; };
struct Bar :Foo { };
typedef multi_index_container< Bar, indexed_by< ordered_unique< member<Foo, int, &Bar::a> > >
Bar_container;
Notice I have to use "Foo" in the "member<" line.
Yes, this is an odd C++ restriction with pointers to member functions when used as non-type template parameters: although Bar inherits from Foo, &Bar::a (which is an alias for &Foo::a) is not seen (statically) as a valid int (Bar:: *) --usual base-derived relationships don't apply here. That's why you had to use Foo as the base class of member. BTW, the expression member<Foo, int, &Bar::a> is entirely equivalent to member<Foo, int, &Foo::a> although the latter is probably clearer.
However, even with this, when trying to do a search: [...] I get this:
/usr/include/boost/multi_index/member.hpp: [...] multitest2.cc:55: instantiated from here /usr/include/boost/multi_index/member.hpp:84: error: no match for 'operator*' in '*x'
I've tried a few alternatives such as providing a custom compare function but I always get this error. It seems to have something to do with the fact that the key is in the base class. If I move the key to the derived class (and change the "member<" line), it works fine.
Surely there's a way to do this. Anyone know how ?
Using gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21) and libboost 1.33.1.
Your code will work out of the box with Boost 1.34, where some issues about key extractors being fed derived classes are solved (see bullet 3 of http://boost.org/libs/multi_index/doc/release_notes.html#boost_1_34 ). In case you can't upgrade to Boost 1.34, you can use a custom key extractor to work around the problem: struct Bar_a_extractor { typedef int result_type; int operator()(const Bar& b)const { return b.a; } }; using namespace boost::multi_index; typedef multi_index_container< Bar, indexed_by< ordered_unique< Bar_a_extractor > >
Bar_container;
Hope this helps, Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

Hi, Indeed everything compiles again with boost 1.34! Thanks alot, Andrej --- Joaquín Mª López Muñoz <joaquin@tid.es> wrote:
Hello Andrej,
Andrej van der Zee ha escrito:
Hi,
I'm trying to store these classes in a multi_index:
struct Foo { int a; };
struct Bar :Foo { };
typedef multi_index_container< Bar, indexed_by< ordered_unique< member<Foo, int, &Bar::a> > >
Bar_container;
Notice I have to use "Foo" in the "member<" line.
Yes, this is an odd C++ restriction with pointers to member functions when used as non-type template parameters: although Bar inherits from Foo, &Bar::a (which is an alias for &Foo::a) is not seen (statically) as a valid int (Bar:: *) --usual base-derived relationships don't apply here. That's why you had to use Foo as the base class of member. BTW, the expression
member<Foo, int, &Bar::a>
is entirely equivalent to
member<Foo, int, &Foo::a>
although the latter is probably clearer.
However, even with this, when trying to do a search: [...] I get this:
/usr/include/boost/multi_index/member.hpp: [...] multitest2.cc:55: instantiated from here /usr/include/boost/multi_index/member.hpp:84: error: no match for 'operator*' in '*x'
I've tried a few alternatives such as providing a custom compare function but I always get this error. It seems to have something to do with the fact that the key is in the base class. If I move the key to the derived class (and change the "member<" line), it works fine.
Surely there's a way to do this. Anyone know how ?
Using gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21) and libboost 1.33.1.
Your code will work out of the box with Boost 1.34, where some issues about key extractors being fed derived classes are solved (see bullet 3 of
http://boost.org/libs/multi_index/doc/release_notes.html#boost_1_34
). In case you can't upgrade to Boost 1.34, you can use a custom key extractor to work around the problem:
struct Bar_a_extractor { typedef int result_type;
int operator()(const Bar& b)const { return b.a; } };
using namespace boost::multi_index;
typedef multi_index_container< Bar, indexed_by< ordered_unique< Bar_a_extractor > >
Bar_container;
Hope this helps,
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
___________________________________________________________ New Yahoo! Mail is the ultimate force in competitive emailing. Find out more at the Yahoo! Mail Championships. Plus: play games and win prizes. http://uk.rd.yahoo.com/evt=44106/*http://mail.yahoo.net/uk
participants (2)
-
Andrej van der Zee
-
Joaquín Mª López Muñoz