查找嵌套提升的multi_index_container [英] Lookup on nested boost multi_index_container

查看:146
本文介绍了查找嵌套提升的multi_index_container的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下code

struct VersionData
{
    VersionData();
    VersionData(VersionData&& rhs);
    int     m_versionId;
    int     m_weight;
    int     m_pId;
    bool    m_hdi;
};

struct VersionId{};

typedef boost::multi_index_container<
    VersionData,
    bmi::indexed_by<
        bmi::ordered_non_unique<
            bmi::tag<VersionId>,
            bmi::member<VersionData, int, &VersionData::m_versionId>
        >
    >
> VersionDataContainer;

struct VersionsData
{
    VersionsData();
    VersionsData(VersionsData&& rhs);
    int m_sdGroupId;
    int m_retId;
    VersionDataContainer m_versionData;
};

struct mvKey{};

typedef boost::multi_index_container<
    VersionsData,
    bmi::indexed_by<
    bmi::ordered_unique<
            bmi::tag<mvKey>,
            bmi::composite_key<
                VersionsData,
                bmi::member<VersionsData,int, &VersionsData::m_subdeliveryGroupId>,
                bmi::member<VersionsData,int, &VersionsData::m_retargetingId>
            >
        >
    >
> mvDataContainer;

mvDataContainer m_data;

的意图是使用mvDataContainer但在某些情况下,我需要在VersionData所有VersionsData查找组合键来查找。像m_data.get&LT; mvKey > equal_range(make_tuple(忽略,忽视,无视))获得&LT;。 VERSIONID > equal_range(123456);

第一个问题,是可以实现的?

第二,这是使用嵌套multi_index_containers正确的方法?任何性能影响/收益?

The intention is to lookup using the composite key in mvDataContainer but in some cases I need to lookup in VersionData across all VersionsData. Something like m_data.get<mvKey>.equal_range(make_tuple(ignore, ignore, ignore)).get<VersionId>.equal_range(123456);
First question, is it achievable?
Second, is this the right approach to use nested multi_index_containers? any performance impacts/gains?

推荐答案

在除了对方的回答暗示为整个表一个容器中,这里的基础上的升压侵入多集

In addition to the other answer suggesting a single container for the whole table, here's the idea based on Boost Intrusive multiset

看它的 住在Coliru

See it Live On Coliru

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/composite_key.hpp>

// for intrusive multiset
#include <boost/intrusive/set.hpp>
#include <boost/range/iterator_range.hpp>
#include <iostream>

namespace bmi = boost::multi_index;
namespace bi  = boost::intrusive;

struct VersionData : bi::set_base_hook<bi::link_mode<bi::auto_unlink> > {
    VersionData(int versionId, int weight=0, int pId=0, bool hdi=false) : 
        m_versionId(versionId), m_weight(weight), m_pId(pId), m_hdi(hdi) { }

    int     m_versionId;
    int     m_weight;
    int     m_pId;
    bool    m_hdi;

    friend std::ostream& operator<<(std::ostream& os, VersionData const& vd) {
        return os << "{ " << vd.m_versionId << " " << vd.m_weight << " " << vd.m_pId << " " << vd.m_hdi << " }";
    }

    struct ById {
        bool operator()(VersionData const& a, VersionData const& b) const  { return a.m_versionId < b.m_versionId; }
    };
};

typedef bi::multiset<VersionData, bi::constant_time_size<false>, bi::compare<VersionData::ById> > VersionIndex;

typedef boost::multi_index_container<
    VersionData,
    bmi::indexed_by<
        bmi::ordered_non_unique<
            bmi::tag<struct VersionId>,
            bmi::member<VersionData, int, &VersionData::m_versionId>
        >
    >
> VersionDataContainer;

struct VersionsData
{
    int m_subdeliveryGroupId;
    int m_retargetingId;

    VersionDataContainer m_versionData;
};

typedef boost::multi_index_container<
    VersionsData,
    bmi::indexed_by<
    bmi::ordered_unique<
            bmi::tag<struct mvKey>,
            bmi::composite_key<
                VersionsData,
                bmi::member<VersionsData,int, &VersionsData::m_subdeliveryGroupId>,
                bmi::member<VersionsData,int, &VersionsData::m_retargetingId>
            >
        >
    >
> mvDataContainer;

void insert(
        mvDataContainer& into, VersionIndex& global_version_index,
        int subdeliveryGroupId, int retargetingId, int
        versionId, int weight, int pId, bool hdi) 
{
    auto& mainIdx = into.get<mvKey>();
    auto insertion = mainIdx.insert(VersionsData { subdeliveryGroupId, retargetingId, VersionDataContainer {} });
    mainIdx.modify(insertion.first, [&](VersionsData& record) {
            auto insertion = record.m_versionData.insert(VersionData { versionId, weight, pId, hdi });
            global_version_index.insert(const_cast<VersionData&>(*insertion.first));
    });
}

int main() {

    VersionIndex global_version_index;
    mvDataContainer table;

    insert(table, global_version_index, 21, 10,                1,  100, 123, false);
    insert(table, global_version_index, 9,  27,                2,  90,  123, false);
    insert(table, global_version_index, 12, 25,                3,  110, 123, true);
    insert(table, global_version_index, 10, 33, /*version 8:*/ 8,  80,  123, false);
    insert(table, global_version_index, 4,  38,                5,  101, 124, false);
    insert(table, global_version_index, 33, 7,                 6,  91,  124, false);
    insert(table, global_version_index, 34, 27,                7,  111, 124, true);
    insert(table, global_version_index, 9,  11, /*version 8:*/ 8,  81,  124, false);
    insert(table, global_version_index, 0,  12,                9,  99,  125, false);
    insert(table, global_version_index, 35, 39, /*version 8:*/ 8,  89,  125, false);
    insert(table, global_version_index, 15, 15,                11, 109, 125, true);
    insert(table, global_version_index, 25, 32, /*version 8:*/ 8,  79,  125, false);

    // debug table output
    assert(table.size()==12);

    // so now you can do:
    std::cout << "---\nQuerying for version id 8:\n";
    for (auto& record : boost::make_iterator_range(global_version_index.equal_range(8)))
        std::cout << record << "\n";

    table.erase(table.find(boost::make_tuple(10,33))); // auto unlinks from global_version_index

    std::cout << "---\nQuerying for version id 8:\n";
    for (auto& record : boost::make_iterator_range(global_version_index.equal_range(8)))
        std::cout << record << "\n";
}

打印:

---
Querying for version id 8:
{ 8 80 123 0 }
{ 8 81 124 0 }
{ 8 89 125 0 }
{ 8 79 125 0 }
---
Querying for version id 8:
{ 8 81 124 0 }
{ 8 89 125 0 }
{ 8 79 125 0 }

这篇关于查找嵌套提升的multi_index_container的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆