2

equal_range によって照会され、range::join および boost::any_range を使用して関数から結果が返されるブースト multi_index_container を使用してい
ます、参照についてはよくわかりません。例:

typedef boost::any_range<TestData, boost::random_access_traversal_tag,
                         const TestData &, std::ptrdiff_t> TestRange;

今私が必要としているのは、boost::sort、unique などの範囲変更アルゴリズムを使用することです。これは、範囲内の要素の constness のために明らかに範囲で実行できません。
要素を新しいコンテナにコピーする以外の回避策はありますか?

編集 1:
構造体と 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;
4

2 に答える 2

2

OK、範囲を取得すると、要素の順序がインデックスによって固定されるため、並べ替えたり、何らかの方法で再配置したりすることはできません。これは、要素の定数によって強制されるインデックスの絶対的に基本的な不変式です。 a と言って見つけますstd::set。外部コンテナへの完全なコピーを行うのではなく、後で必要に応じて操作できる元の要素へのポインタまたは参照から、より軽量なビューを作成できます。これは、要素に対する sstd::vectorのsとして構築されたビューの例です。std::reference_wrapper

Live On Coliru

#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} 
于 2014-12-10T20:07:53.147 に答える
1

multi_index コンテナにデータを入れる必要がないように思えます。multi_index コンテナー (名前のヒント) は、不変データを格納しながら、そのデータに対して複数のインデックス (または制約付きのビュー) を維持するように設計されています。

mutableデータを更新できるようにする場合は、データの一部を作成できますが、そのmutable部分がインデックスの構築に関与しないようにする必要があります。

本当にやりたいことがデータを変更し、結果として新しいインデックスを生成することである場合、2 つのオプションがあります - 削除して再挿入するか、(より良い) boost::multi_index を使用しないでください。

1 つのアプローチは、ベクターを使用して独自のアドホック インデックスを維持することです。

たとえば、文字列のベクトル内の一意のエントリのインデックス (単純にするため):

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;
}
于 2014-12-10T17:53:51.247 に答える