Boost.MultiIndex タプルのi番目の要素をキーにする

【tuples, multi-index】 tuples::get as key extractor


MultiIndexのKey Extractorにはidentity(それ自身), member(メンバ変数ポインタ), mem_fun(メンバ関数ポインタ), global_fun(グローバル関数へのポインタ)がありますが、タプルをコンテナの要素とし、そのi番目の要素をキーとするようなインデックスはどうすればできるかという問題。


単純にglobal_fun >とすることは残念ながらできないので、
タプル用のKey Extractorを作る必要があります。

#include <iostream>
#include <string>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/make_vector.hpp>
#include <boost/fusion/include/at_c.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/type_traits/remove_reference.hpp>

using namespace boost::multi_index;
namespace fusion = boost::fusion;

template <class Tuple, int N>
struct tuple_member_extractor {
    typedef
        typename boost::remove_reference<
            typename fusion::result_of::at_c<Tuple, N>::type
        >::type
    result_type;

    const result_type& operator()(const Tuple& t) const
    {
        return fusion::at_c<N>(t);
    }
};

typedef fusion::vector<int, std::string, double> X;

typedef multi_index_container<
    X,
    indexed_by<
        ordered_unique<tuple_member_extractor<X, 0> >
    >
> container;

int main()
{
    container c;
    c.insert(fusion::make_vector(3, "Akira", 7.89));
    c.insert(fusion::make_vector(1, "Johnny", 4.56));
    c.insert(fusion::make_vector(4, "Millia", 1.23));

    std::cout << boost::make_iterator_range(c) << std::endl;
}
(1 Johnny 4.56)(3 Akira 7.89)(4 Millia 1.23)

Key Extractorの内容としては、単に何番目かをパラメータで受け取って、at_cでI番目を参照して返すだけです。