【问题标题】:boost::multi_index_container: Take equal_range from arbitrary index, implement loop only onceboost::multi_index_container:从任意索引中获取equal_range,只执行一次循环
【发布时间】:2014-08-05 07:36:33
【问题描述】:

我有一个multi_index_container,基本上看起来像这样:

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;

我实例化这样一个容器并像这样使用它的索引:

MyContainer c;

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

现在,在运行时,我想对两个索引之一执行equal_range。实际使用哪个索引,取决于当前配置。我想要完成的是这样的:

// 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)
  ...

我不知道该怎么做。事实证明,index1.equal_range 的返回类型是一对不同于index2.equal_range 返回的迭代器。两者有共同的基本类型吗?看看我的例子,SomeType 应该是什么样子?我不想在我的代码中为每个可能使用的索引重复 for 循环。

【问题讨论】:

    标签: c++ boost boost-multi-index


    【解决方案1】:

    不要尝试使用范围进行类型擦除,而是将循环逻辑放入 lambda 并使用 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;
    }
    

    【讨论】:

    • 谢谢,这确实有帮助!它引导我进入下一个问题,我可能不得不打破循环,所以for_each 并不是我所需要的,但那是另一回事......
    • 如果您需要跳出 for_each 循环,请尝试使用 std::find_if 代替,一旦条件为真(您在 lambda 中返回 true),否则返回 false 以继续循环。
    • 感谢您的补充,johnco3,find_if 不在我的活跃词汇中,但我能够自己做一个模板化循环 lambda。
    猜你喜欢
    • 2013-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多