読者です 読者をやめる 読者になる 読者になる

ベターsetとしてmulti indexを使う

C++

コンテナに複数のインデックスを持てるBoost.MultiIndexですが、単一のインデックスだけを持たせるだけでも便利に使えます。ここでは、std::setを置き換えて使ってみます。


std::setにユーザー定義型を格納する場合、キーの比較を自分で定義する必要があります。そしてその比較が一部のメンバ変数だけで完結する場合、std::setでは比較に必要なメンバ変数以外に、ダミーの値を入れたオブジェクトを作る必要があります。

#include <iostream>
#include <set>

struct X {
    int a = 0;
    int b = 0;
    int c = 0;

    X(int a, int b, int c)
        : a(a), b(b), c(c) {}
};

struct XLess {
    bool operator()(const X& x, const X& y) const
    {
        return x.b < y.b;
    }
};

int main()
{
    std::set<X, XLess> x;

    x.insert({1, 3, 3});
    x.insert({2, 1, 2});
    x.insert({3, 4, 1});

    decltype(x)::const_iterator it = x.find({-1, 1, -1}); // bだけが必要なので、aとcはダミー値
    if (it != x.end()) {
        std::cout << it->a << std::endl;
    }
    else {
        std::cout << "not found" << std::endl;
    }
}
2

Boost.MultiIndexの場合は、キー比較に使用するメンバ変数/メンバ関数を指定できるので、便利なsetとして使用できます。

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

struct X {
    int a = 0;
    int b = 0;
    int c = 0;

    X(int a, int b, int c)
        : a(a), b(b), c(c) {}
};

using namespace boost::multi_index;
using Container = multi_index_container<
    X,
    indexed_by<
        ordered_unique<member<X, int, &X::b>> // bをキーにする
    >
>;

int main()
{
    Container c;

    c.insert({1, 3, 3});
    c.insert({2, 1, 2});
    c.insert({3, 4, 1});

    decltype(c)::const_iterator it = c.find(1); // bの値だけ指定して検索
    if (it != c.end()) {
        std::cout << it->a << std::endl;
    }
    else {
        std::cout << "not found" << std::endl;
    }
}
2

検索が簡単にできるようになりました。