是否有可能在boost :: multi_index_container中只有索引某些元素的索引?

时间:2015-11-10 11:54:10

标签: c++ boost

是否可以在boost::multi_index_container中创建索引 只索引容器中的一些元素?

如果你有一个boost多索引容器:

using Nodes = boost::multi_index_container<
    Node,
    indexed_by<
        sequenced<>,
        ordered_unique<
            tag<ordered_by_parent_id>,
            const_mem_fun<Node, boost::optional<unsigned int>, &Node::parentId>
        >
    >
>;

容器中的元素具有方法

const boost::optional<int> Node::parentId()

你可能想要一个关于Node::parentId()的返回值的索引 但如果你实际上只需要一个非空值的索引, 为集合中的所有元素创建索引似乎很浪费。

您可以创建第二个std容器,其中包含指向子集的指针 具有有效父ID的节点,但是有一种很好的方法可以将其作为多索引容器上的附加索引来处理吗?

1 个答案:

答案 0 :(得分:2)

不,你不能。

当然,您可以使用非唯一索引,但仍有所有无父条目的开销。

可以做什么,但是将指针放在一个单独的“索引”容器中。然后,上有责任保护这些容器的同步(以及指向对象的生命周期)。

更新您甚至可以透明地使用引用包装器:

using ParentIndex = bmi::multi_index_container<
    boost::reference_wrapper<Node const>,
    bmi::indexed_by<
        bmi::ordered_non_unique<
            bmi::tag<struct ordered_by_parent_id>,
            bmi::const_mem_fun<Node, boost::optional<unsigned int>, &Node::parentId>
        >
    >
>;

这是一个演示:

<强> 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 <boost/optional.hpp>
#include <boost/optional/optional_io.hpp>
#include <iostream>

namespace bmi = boost::multi_index;

struct Node {
    unsigned int Id;
    boost::optional<unsigned int> for_demo;
    boost::optional<unsigned int> parentId() const { return for_demo; };
};

static std::ostream& operator<<(std::ostream& os, Node const& n) {
    return os << "{" << n.Id << ", " << n.parentId() << "}";
}

using Nodes = bmi::multi_index_container<
    Node,
    bmi::indexed_by<
        bmi::sequenced<>
    >
>;

using ParentIndex = bmi::multi_index_container<
    boost::reference_wrapper<Node const>,
    bmi::indexed_by<
        bmi::ordered_non_unique<
            bmi::tag<struct ordered_by_parent_id>,
            bmi::const_mem_fun<Node, boost::optional<unsigned int>, &Node::parentId>
        >
    >
>;

int main() {
    Nodes table {
        {1, boost::none}, {2, 5}, {3, boost::none}, {4, 5}, {5, 5}, {6, 2}
    };

    ParentIndex extra;
    for (auto const& e : table) 
        if (e.parentId()) extra.emplace(e);

    for (auto& e : table) 
        std::cout << e.Id << " ";

    std::cout << "\nParented: ";

    for (Node const& e : extra) 
        std::cout << e << "; ";
}