获取boost :: multi_index_container

时间:2016-01-08 08:53:22

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

(不通过容器迭代)

我尝试用一​​个boost :: multi_index_container替换多个std容器。

下面的boost :: multi_index_container有两个索引

using Boxes = boost::multi_index_container<
    Box,
    indexed_by<
        sequenced<
            tag<ordered_by_insertion>
        >,
        ordered_unique<
            tag<ordered_by_id>,
            const_mem_fun<Box, set_id_type_const_reference, &Box::id>
        >
    >
>;

需要保留元素添加到容器的顺序, 所以第一个索引是插入序列(ordered_by_insertion)。

元素由id唯一标识, 所以第二个索引是唯一的id(ordered_by_id)。

如何使用唯一ID来有效地检索元素的插入顺序位置。

有没有办法将 ordered_by_insertion 转换为从对象到位置的双向地图? 或者从Box :: id到位置创建第三个索引?

2 个答案:

答案 0 :(得分:4)

以下projects从索引#1到索引#0的迭代器:

Boxes b=...;
auto it1=b.get<1>().find(id);
auto it0=b.project<0>(it1);

您可以从中获取索引#0中的位置,但是线性时间,因为序列索引迭代器只是双向的:

auto pos=std::distance(b.begin(),it0);

好消息是,如果您使用random_access索引而不是sequenced,则计算pos是常数时间;你甚至可以简单地写它:

auto pos=it0-b.begin();

答案 1 :(得分:3)

你可以这样做:

<强> Live On Coliru

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <iostream>

namespace  bmi = boost::multi_index;

using set_id_type_const_reference = int const&;

struct Box {
    int _id;
    std::string name;

    set_id_type_const_reference id() const { return _id; }
};

using Boxes = boost::multi_index_container<
    Box,
    bmi::indexed_by<
        bmi::sequenced<bmi::tag<struct ordered_by_insertion> >,
        bmi::ordered_unique<
            bmi::tag<struct ordered_by_id>,
            bmi::const_mem_fun<Box, set_id_type_const_reference, &Box::id>
        >
    >
>;

int main() {
    Boxes boxes { {1,"One"}, {17,"Seventeen"}, {8,"Eight"}, {3,"Three"} };

    auto& by_ins = boxes.get<ordered_by_insertion>();
    auto& by_id  = boxes.get<ordered_by_id>();

    for (auto i : { 8,17,1,3 }) {
        auto it = by_id.find(i);
        auto position = distance(by_ins.begin(), bmi::project<0>(boxes, it));

        std::cout << "Found " << it->name << " with insertion-order position " << position << "\n";
    }

}

打印:

Found Eight with insertion-order position 2
Found Seventeen with insertion-order position 1
Found One with insertion-order position 0
Found Three with insertion-order position 3

考虑使用random_access来提高distance通话效率:http://www.boost.org/doc/libs/1_60_0/libs/multi_index/doc/reference/rnd_indices.html