ネストされた値に基づいたインデックスでマルチインデックスコンテナーをブーストする

StackOverflow https://stackoverflow.com/questions/1628321

  •  06-07-2019
  •  | 
  •  

質問

次のようなオブジェクトがある場合:

struct Bar {
    std::string const& property();
};

このようにマルチインデックスコンテナを作成できます:

struct tag_prop {};
typedef boost::multi_index_container<
    Bar,
    boost::multi_index::indexed_by<
        boost::multi_index::ordered_non_unique<
            boost::multi_index::tag<tag_prop>,
            boost::multi_index::const_mem_fun<
                Bar, const std::string&, &Bar::property
            >
        >
    >
    , ... other indexes
> BarContainer;

ただし、次のようなクラスがある場合:

struct Foo {
   Bar const& bar();
};

Foo オブジェクトのコンテナの .bar()。property()にインデックスを構築するにはどうすればよいですか?

通常、 boost :: bind の呼び出しをネストしますが、マルチインデックスコンテナーのコンテキストでそれを動作させる方法がわかりません。

役に立ちましたか?

解決

Fooの2つのインスタンスを取り、そのoperator()が両方のインスタンスでFoo :: bar()を呼び出すことができる述語オブジェクトを作成する必要があると思います。

次のようなもの

struct MyPredicate
{

    bool operator() (const Foo& obj1, const Foo& obj2) const
    {
        // fill in here
    }
};

次に使用

...
boost::multi_index::ordered_unique<boost::multi_index::tag<tag_prop>, 
    boost::multi_index::identity<Foo>, MyPredicate>,
...

MultiIndex Ordered index referenceをご覧ください

他のヒント

ユーザー定義のコンパレーターを提供する代わりに、ユーザー定義の key extractor

を記述できます。
struct FooBarPropertyExtractor
{
  typedef std::string result_type;
  const result_type& oeprator()(const Foo& f)
  {
    return f.bar().property();
  }
};

...

typedef boost::multi_index_container<
        Bar,
        boost::multi_index::indexed_by<
                boost::multi_index::ordered_non_unique<
                        boost::multi_index::tag<tag_prop>,
                        FooBarPropertyExtractor
                >
        >
        , ... other indexes
> FooContainer;

Boost.MultiIndexキーエクストラクターの高度な機能

ラムダを使用して単純なことをするのが好きなのと同じように、これはすぐに退化する可能性があります:)

あなたの場合、それはもう少し複雑なので、無料の関数または述語コンパレータのいずれかに依存します。

述語には、型をより明確に定義するという利点があるため、通常は実際にそれを取り込むのが簡単です。

また、読みやすくするために、通常、インデックスをtypedefします。

namespace mi = boost::multi_index;

struct FooComparator
{
  bool operator()(Foo const& lhs, Foo const& rhs) const
  {
    return lhs.bar().property() < rhs.bar().property();
  }
};

typedef mi::ordered_unique <
          mi::tag<tag_prop>,
          mi::identity<Foo>,
          FooComparator
        > foo_bar_index_t;

typedef boost::multi_index_container <
          Foo,
          mi::indexed_by < 
            foo_bar_index_t,
            // ... other indexes
          >
        > foo_container_t;

述語アプローチには、より定型的なコードが必要ですが、比較ロジックをインデックス定義からうまく分離できます。インデックス定義自体はコンテナ定義から分離されています。

明確な分離により、構造が一目で見やすくなります。

scroll top