Boost logo

Boost Users :

From: Joaquín Mª López Muñoz (joaquin_at_[hidden])
Date: 2007-06-13 02:09:50


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 list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net