【问题标题】:How to retrieve element from boost::multi_index_container如何从 boost::multi_index_container 中检索元素
【发布时间】:2019-07-03 11:51:45
【问题描述】:

我正在尝试使用唯一的数字 id 索引从 boost::multi_index_container 中检索一个值。我以前从未使用过boost::multi_index_container,所以我很难理解它们是如何工作的。它们看起来有点像数据库,我想做的就是通过指定 id 来检索项目。任何帮助将不胜感激。

这是数据类型:

typedef boost::multi_index_container<
    // Multi index container holds pointers to the subnets.
    Subnet6Ptr,
    // The following holds all indexes.
    boost::multi_index::indexed_by<
        // First is the random access index allowing for accessing
        // objects just like we'd do with a vector.
        boost::multi_index::random_access<
            boost::multi_index::tag<SubnetRandomAccessIndexTag>
        >,
        // Second index allows for searching using subnet identifier.
        boost::multi_index::ordered_unique<
            boost::multi_index::tag<SubnetSubnetIdIndexTag>,
            boost::multi_index::const_mem_fun<Subnet, SubnetID, &Subnet::getID>
        >,
        // Third index allows for searching using an output from toText function.
        boost::multi_index::ordered_unique<
            boost::multi_index::tag<SubnetPrefixIndexTag>,
            boost::multi_index::const_mem_fun<Subnet, std::string, &Subnet::toText>
        >
    >
> Subnet6Collection;

Subnet6Collection 对象是在 dhcpv6-server (KEA) 加载其配置文件时创建的。此文件包含每个子网的可选数字 id 值,数据类型中为 SubnetID

我想通过指定SubnetID 来检索Subnet6Ptr

【问题讨论】:

  • 这是一个数据库成语。为什么不直接使用(许多非常好的)c++ API 到 SQLite?或者至少将解决方案描述为基于关系数据库。假设键值存储由于某种原因是不够的......而且最低限度是你“允许”使用哪个 C++。
  • @ChefGladiator 他们正在尝试使用某些库提供的Subnet6Collection 类型的对象,而不是重写库以使用SQL

标签: c++ boost


【解决方案1】:

是的,Mutli-index 可能是一个难以使用的野兽。正如我在a different answer 中所写,“Boost.Multi-index 提供了一个极其可定制的界面,但代价是提供了一个极其复杂的界面。”

基本上,当您想要访问容器的内容时​​,您可以通过它的索引之一来实现。因此,您首先获取对要使用的索引的引用(在您的情况下标记为SubnetSubnetIdIndexTag),然后将该索引视为容器。哪个容器取决于索引的类型。对于排序的唯一索引(如您的情况),这有点像 std::map (但迭代器仅指向值),或者像 std::set 具有仅比较 ID 的透明比较器。

这是它在代码中的样子:

Subnet6Collection coll = something();
SubnetID idToLookFor = something2();

auto& indexById = coll.index<SubnetSubnetIdIndexTag>();
auto it = index.find(idToLookFor);
if (it != index.end()) {
  Subnet6Ptr p = *it;
} else {
  // No such ID found
}

【讨论】:

    【解决方案2】:

    感谢您的回答。

    我尝试了以下方法(SubnetID 只是 uint32_t,所以我使用 10 进行测试):

    SubnetID id = 10;
    Subnet6Collection coll;
    
    auto& indexById = coll.index<SubnetSubnetIdIndexTag>();
    auto it = index.find(id);
    if (it != index.end()) {
      Subnet6Ptr p = *it;
    } else {
      // No such ID found
    }
    

    但它不能编译:

    Opt18_lease_select.cc:38:24:错误:无效使用 'struct boost::multi_index::multi_index_container, boost::multi_index::indexed_by >, boost::multi_index::ordered_unique, boost::multi_index::const_mem_fun >, boost::multi_index::ordered_unique, boost::multi_index::const_mem_fun, &isc::dhcp::Subnet::toText> > > >::index'

    auto& indexById = coll.index<SubnetSubnetIdIndexTag>();
                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    

    Opt18_lease_select.cc:39:17:错误:没有上下文类型信息的重载函数

     auto it = index.find(id);
                     ^~~~
    

    Opt18_lease_select.cc:40:17:错误:没有上下文类型信息的重载函数

     if (it != index.end()) {
                     ^~~
    

    好像 index() find(), end() 不能这样用,还是我只是少了一些头文件?

    【讨论】:

    • s/coll.index/coll.get, s/index/indexById,阅读文档
    猜你喜欢
    • 1970-01-01
    • 2021-04-25
    • 2014-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-02
    • 1970-01-01
    相关资源
    最近更新 更多