boot :: multi_index获取唯一索引的随机访问权限

时间:2017-04-03 18:20:22

标签: c++ boost containers multi-index

我的应用程序中有一个boost::multi_index容器,它包含对象的共享指针(std::shared_ptr)。正如我从文档中所理解的那样,它创建了一个树结构,并在唯一索引上进行双向访问。是否可以告诉容器具有一个数组结构,该结构具有对唯一索引的随机访问(类似boost::flat_set)?

2 个答案:

答案 0 :(得分:3)

没有MultiIndex

您当然可以完全按照您的描述进行操作:

<强> Live On Coliru

#include <boost/container/flat_set.hpp>
#include <memory>
#include <vector>
#include <iostream>

template <typename V, typename... Init>
auto make_shared_flat_set(Init&&... values) {
    return boost::container::flat_set<std::shared_ptr<V> > { 
        std::make_shared<V>(std::forward<Init>(values))...
    };
}

int main() {
    using sptr = std::shared_ptr<std::string>;
    auto const set = make_shared_flat_set<std::string>("one", "two", "three", "four", "Hungary");

    // the set-like interface: (ordered_unique)
    std::cout << "set: ";
    for (auto& e : set) std::cout << *e << " ";

    {
        // let's make a random access copy:
        std::vector<sptr> random_access(set.begin(), set.end());
        std::cout << "\ncopy: ";
        for (auto& e : random_access) std::cout << *e << " ";
    }

    {
        // let's make a random access view:
        using spref = std::reference_wrapper<sptr const>;
        std::vector<spref> random_access(set.begin(), set.end());
        std::cout << "\nview: ";
        for (sptr const& e : random_access) std::cout << *e << " ";
    }
}

打印

set: one two three four Hungary 
copy: one two three four Hungary 
view: one two three four Hungary 

使用MultiIndex

<强> Live On Coliru

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <memory>
#include <iostream>

namespace bmi = boost::multi_index;

template <typename V> using Table = bmi::multi_index_container<std::shared_ptr<V>,
        bmi::indexed_by<
            bmi::random_access<bmi::tag<struct ra_idx> >,
            bmi::ordered_unique<bmi::tag<struct set_idx>, bmi::identity<V> >
        >
    >;

template <typename V, typename... Init>
auto make_shared_flat_set(Init&&... values) {
    return Table<std::string> { 
        std::make_shared<V>(std::forward<Init>(values))...
    };
}

int main() {
    auto const set = make_shared_flat_set<std::string>("one", "two", "three", "four", "Hungary");

    // the set-like interface: (ordered_unique)
    auto& as_set = set.get<set_idx>();

    std::cout << "set: ";
    for (auto& e : as_set) std::cout << *e << " ";

    // the random access interface:
    std::cout << "\nrandom access: ";
    auto& random_access = set.get<ra_idx>();
    for (auto& e : random_access) std::cout << *e << " ";
}

打印:

set: Hungary four one three two 
random access: one two three four Hungary 

奖金:

要将random_access索引放入与set相同的顺序,请使用重新排列:

// put the random access in the same order as the set:
random_access.rearrange(make_ro_view(as_set).begin());

std::cout << "\nrandom access (rearranged): ";
for (auto& e : random_access) std::cout << *e << " ";

<强> Live On Coliru

打印

set: Hungary four one three two 
random access: one two three four Hungary 
random access (rearranged): Hungary four one three two

答案 1 :(得分:3)

添加到sehe的答案中,Boost.MultiIndex有ranked indices提供对数时间位置访问,与通常的有序索引接口相对 - 不完全是随机访问,但可能足以满足您的需求。

<强> Live On Coliru

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/ranked_index.hpp>
#include <memory>
#include <iostream>

namespace bmi = boost::multi_index;

template <typename V> using Table = bmi::multi_index_container<std::shared_ptr<V>,
        bmi::indexed_by<
            bmi::ranked_unique<bmi::tag<struct set_idx>, bmi::identity<V> >
        >
    >;

template <typename V, typename... Init>
auto make_shared_flat_set(Init&&... values) {
    return Table<std::string> { 
        std::make_shared<V>(std::forward<Init>(values))...
    };
}

int main() {
    auto const set = make_shared_flat_set<std::string>("one", "two", "three", "four", "Hungary");

    std::cout << "set: ";
    for (auto& e : set) std::cout << *e << " ";

    // the random access interface:
    std::cout << "\npositional access: ";
    for (std::size_t n = 0; n < set.size(); ++n) std::cout << **set.nth(n) << " ";
}

打印

set: Hungary four one three two 
positional access: Hungary four one three two