[英]boost multi_index_container, range mutating algorithms and constness
我正在使用boost multi_index_container,由equal_range查詢,並使用range :: join和boost :: any_range從函數返回結果
any_range Reference參數定義為對該類型的const引用-由於multi_index_container的性質,必須為const,對此引用不確定。 例:
typedef boost::any_range<TestData, boost::random_access_traversal_tag,
const TestData &, std::ptrdiff_t> TestRange;
現在,我需要使用可變范圍算法,例如boost :: sort,unique等,由於范圍內元素的恆定性,顯然不能在范圍上運行。
除了將元素復制到新容器中,是否有其他解決方法?
編輯1:
struct和MIC示例:
struct TestData {
TestData()
: m_strMem01("test"), m_intMem02(rand()),
m_boolMem03(rand() < RAND_MAX / 2) {}
std::string m_strMem01;
int m_intMem02;
bool m_boolMem03;
};
typedef boost::multi_index_container<
TestData,
bmi::indexed_by<
bmi::random_access<bmi::tag<struct RndKey1>>,
bmi::ordered_non_unique<
bmi::tag<struct Key1>,
bmi::composite_key<
TestData,
bmi::member<TestData, std::string, &TestData::m_strMem01>,
bmi::member<TestData, bool, &TestData::m_boolMem03>>>,
bmi::ordered_non_unique<
bmi::tag<struct Key4>,
bmi::composite_key<
TestData,
bmi::member<TestData, std::string, &TestData::m_strMem01>,
bmi::member<TestData, bool, &TestData::m_intMem02>>>,
bmi::ordered_non_unique<
bmi::tag<struct Key2>,
bmi::member<TestData, int, &TestData::m_intMem02>>,
bmi::ordered_non_unique<
bmi::tag<struct Key3>,
bmi::member<TestData, bool, &TestData::m_boolMem03>>>>
TestDataContainer;
好的,一旦有了范圍,您就真的無法對它進行排序或以某種方式重新排列它,因為元素的順序由索引固定-這是元素的恆定性強制執行的索引的絕對基本不變,就像您想要的那樣找到說std::set
。 與其對外部容器進行完整復制,還可以根據原始元素的指針或引用創建一個更輕量級的視圖 ,以供以后按需使用。 這是一個示例,其中視圖構造為std::reference_wrapper
的std::vector
到元素:
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/range/algorithm/sort.hpp>
#include <boost/range/join.hpp>
#include <functional>
#include <iostream>
#include <vector>
using namespace boost::multi_index;
struct X
{
int x,y;
};
std::ostream& operator<<(std::ostream& os,const X& a)
{
return os<<"{"<<a.x<<","<<a.y<<"}";
}
typedef multi_index_container<
X,
indexed_by<
ordered_non_unique<member<X,int,&X::x>>
>
> multi_t;
struct view:std::vector<std::reference_wrapper<const X>>
{
using base=std::vector<std::reference_wrapper<const X>>;
template<typename InputIterator>
view(InputIterator first,InputIterator last):base(first,last){}
template<typename InputIterator>
view(const std::pair<InputIterator,InputIterator> p):base(p.first,p.second){}
};
int main()
{
multi_t m={{0,1},{0,0},{0,2},{1,3},{1,1},{2,0},{2,1}};
view v1=m.equal_range(0); // elements with x==0
view v2=m.equal_range(2); // elements with x==2
auto v3=boost::range::join(v1,v2); // join them
boost::range::sort(v3,[](const X& a,const X& b){return a.y<b.y;}); // sort them by y
for(const auto& x:v3)std::cout<<x<<" "; // output
}
輸出:
{0,0} {2,0} {0,1} {2,1} {0,2}
聽起來好像根本不希望將數據放在multi_index容器中。 multi_index容器(顧名思義)旨在存儲不可變數據,同時針對該數據維護多個索引(或具有約束的視圖)。
如果希望能夠更新一部分數據,則可以使其mutable
,但是必須確保mutable
部分不參與索引構造。
如果您真正想做的是對數據進行變異並生成新的索引,那么您有2個選擇-刪除並重新插入,或者(更好)不要使用boost :: multi_index。
一種方法是使用向量並維護您自己的臨時索引。
例如,字符串向量中的唯一項索引(為簡單起見):
vector<const string*> unique_stable_index(const vector<string>& data)
{
struct less_ptr {
bool operator()(const string* l, const string* r) const {
return *l < *r;
}
};
vector<const string*> result;
set<const string*, less_ptr> seen;
for (const auto& s : data) {
if(seen.insert(&s).second)
result.push_back(&s);
}
return result;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.