查找嵌套提升的multi_index_container [英] Lookup on nested boost 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屋!