Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Boost multi-index container with index based on nested values

If I have an object like this:

struct Bar {
    std::string const& property();
};

I can create a multi-index container for it like this:

struct tag_prop {};
typedef boost::multi_index_container<
    Bar,
    boost::multi_index::indexed_by<
        boost::multi_index::ordered_non_unique<
            boost::multi_index::tag<tag_prop>,
            boost::multi_index::const_mem_fun<
                Bar, const std::string&, &Bar::property
            >
        >
    >
    , ... other indexes
> BarContainer;

But if I have a class like this:

struct Foo {
   Bar const& bar();
};

How can I construct an index on .bar().property() for a container of Foo objects?

Normally I would nest calls to boost::bind, but I can't figure out how to make it work in the context of a multi-index container.

like image 613
Tim Sylvester Avatar asked Oct 27 '09 01:10

Tim Sylvester


2 Answers

Rather than providing a user-defined comparator, you can write a user-defined key extractor:

struct FooBarPropertyExtractor
{
  typedef std::string result_type;
  const result_type& oeprator()(const Foo& f)
  {
    return f.bar().property();
  }
};

...

typedef boost::multi_index_container<
        Bar,
        boost::multi_index::indexed_by<
                boost::multi_index::ordered_non_unique<
                        boost::multi_index::tag<tag_prop>,
                        FooBarPropertyExtractor
                >
        >
        , ... other indexes
> FooContainer;

See Advanced features of Boost.MultiIndex key extractors

like image 127
Joaquín M López Muñoz Avatar answered Sep 17 '22 22:09

Joaquín M López Muñoz


I believe you need to create a predicate object that takes two instances of Foo and its operator() can call Foo::bar() on both instances.

Something like

struct MyPredicate
{

    bool operator() (const Foo& obj1, const Foo& obj2) const
    {
        // fill in here
    }
};

and then use

...
boost::multi_index::ordered_unique<boost::multi_index::tag<tag_prop>, 
    boost::multi_index::identity<Foo>, MyPredicate>,
...

Check out MultiIndex Ordered indices reference

like image 26
Stephen Nutt Avatar answered Sep 20 '22 22:09

Stephen Nutt