3

I have a multi_index_container that looks basically like this:

struct MyStruct {
  int a, b, c;
};

struct Tag1;
struct Tag2;

typedef multi_index_container<
  MyStruct,
  indexed_by<
    hashed_non_unique<
      tag<Tag1>,
      composite_key<
        MyStruct,
        member<MyStruct, int, &MyStruct::a>,
        member<MyStruct, int, &MyStruct::b>
      >
    >,
    hashed_non_unique<
      tag<Tag2>,
      composite_key<
        MyStruct,
        member<MyStruct, int, &MyStruct::a>,
        member<MyStruct, int, &MyStruct::b>,
        member<MyStruct, int, &MyStruct::c>
      >
    >
  >
> MyContainer;

I instantiate such a container and use its indices like so:

MyContainer c;

MyContainer::index<Tag1>::type& index1 = c.get<Tag1>;
MyContainer::index<Tag2>::type& index2 = c.get<Tag2>;

Now, at runtime, I want to do an equal_range on one of the two indices. Which index is actually used, is dependent on the current configuration. What I'm trying to accomplish is something like this:

// Search in container
SomeType range;
if (useIndex1)
  range = index1.equal_range(...);
else
  range = index2.equal_range(...);

// Loop through range
for (auto i = range.first; i != range.second; ++i)
  ...

I don't know how to do this. As it turns out, the return type of index1.equal_range is a pair of iterators that are different from those returned by index2.equal_range. Is there a common base type to the two? Looking at my example, what would SomeType have to look like? I don't want to repeat the for loop in my code for every index that may possibly be used.

phkoester
  • 801
  • 6
  • 7

1 Answers1

2

Instead of trying to do type erasure with range, put your loop logic into a lambda and apply it using std::for_each:

#include <boost\multi_index_container.hpp>
#include <boost\multi_index\composite_key.hpp>
#include <boost\multi_index\member.hpp>
#include <boost\multi_index\hashed_index.hpp>

using namespace boost::multi_index;

struct MyStruct {
    int a, b, c;
};

struct Tag1;
struct Tag2;

typedef multi_index_container 
<
    MyStruct
  , indexed_by 
    <
        hashed_non_unique
        <
            tag<Tag1>
          , composite_key
            <
                MyStruct
              , member<MyStruct, int, &MyStruct::a>
              , member<MyStruct, int, &MyStruct::b>
            >
        >
      , hashed_non_unique
        <
            tag<Tag2>
          , composite_key
            <
                MyStruct
              , member<MyStruct, int, &MyStruct::a>
              , member<MyStruct, int, &MyStruct::b>
              , member<MyStruct, int, &MyStruct::c>
            >
        >
    >
> MyContainer;

int main()
{
    MyContainer c;

    MyContainer::index<Tag1>::type& index1 = c.get<Tag1>();
    MyContainer::index<Tag2>::type& index2 = c.get<Tag2>();

    //! Add some values
    for (int i = 0; i < 10; ++i)
    {
        MyStruct s = { i, i * 2, i * 3 };
        c.insert(s);
    }

    auto loop = [](const MyStruct& s){ std::cout << "{ " << s.a << ", " << s.b << ", " << s.c << " }" << std::endl; };

    // Search in container
    bool useIndex1 = true;
    if (useIndex1)
    {
        auto range = std::make_pair(index1.begin(), index1.end());
        std::for_each(range.first, range.second, loop);
    }
    else
    {
        auto range = std::make_pair(index1.begin(), index1.end());
        std::for_each(range.first, range.second, loop);
    }

    // Loop through range
    //for (auto i = range.first; i != range.second; ++i)

    return 0;
}
Brandon Kohn
  • 1,612
  • 8
  • 18
  • Thanks, this does help! It leads me to the next problem that I may have to break from the loop, so `for_each` isn't exactly what I need, but that's a different story ... – phkoester Aug 06 '14 at 06:34
  • If you need to break out of the for_each loop, try using std::find_if instead, once the condition is true (you return true in your lambda) otherwise return false to keep looping. – johnco3 Jan 27 '15 at 15:39
  • Thanks for the addition, johnco3, find_if wasn't in my active vocabulary, but I was able to do a templated loop lambda on my own. – phkoester Jan 30 '15 at 22:13