boost::mpl::map から任意の key を持つ pair を抽出


[お題]
boost::mpl::map から任意の key を持つ pair を Sequence として抽出したい。

// key が char 型の pair を抽出したい!!
mpl::map<
    mpl::pair<char,  int>,
    mpl::pair<int,   float>,
    mpl::pair<float, char>,
    mpl::pair<char,  float>,
    mpl::pair<int,   int>
>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/equal.hpp>
#include <boost/mpl/map.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/filter_view.hpp>

namespace mpl = boost::mpl;

// apply_pair は、オワコン
template<typename Lambda, typename P>
struct apply_pair :
    Lambda::apply<
        typename mpl::first<P>::type,
        typename mpl::second<P>::type
    >::type{};

typedef mpl::map<
    mpl::pair<char,  int>,
    mpl::pair<int,   float>,
    mpl::pair<float, char>,
    mpl::pair<char,  float>,
    mpl::pair<int,   int>
> m;

typedef mpl::filter_view<
    m,
//    apply_pair<mpl::lambda<boost::is_same<char, mpl::_1> >::type, mpl::_>
    boost::is_same<char, mpl::first<mpl::_> >  // こっちの方がスマート
> result;


BOOST_MPL_ASSERT(( mpl::equal<
    result
    mpl::vector< mpl::pair<char, int>, mpl::pair<char, float> >
> ));


mpl::filter_view を使用していますが、Pred を定義する場合、

boost::is_same<char, mpl::first<mpl::_>::type>

の様に定義することが出来ないので、(mpl::_ 等を引数に渡した場合は、メタ関数を評価できない!!)
ヘルパー関数 apply_pair を1度噛ませて、メタ関数に first と second を渡しています。


※訂正

boost::is_same<char, mpl::first<mpl::_> >

こう記述することが出来るみたいです。

BOOST_MPL_ASSERT(( 
    apply_pair<
        mpl::lambda<boost::is_same<mpl::_1, mpl::_2> >::type,
        mpl::pair<int, int>
    >::type
));

BOOST_MPL_ASSERT(( 
    apply_pair<
        mpl::lambda<boost::is_same<int, mpl::_2> >::type,
        mpl::pair<void, int>
    >::type
));

こんな感じで、mpl::lambda で定義したメタ関数の mpl::_1 が first で、mpl::_2 が second になります。
mpl::lambda 超便利。
あと mpl::filter_view の戻り値は mpl::map 型ではないので、続けて mpl::at 等を使用する場合は注意が必要です。


[追記]
Twitter で突っ込まれたのですが、これでいいみたいです。

typedef mpl::filter_view<m, boost::is_same<char, mpl::first<mpl::_> > > result;

ああ……mpl::first って、is_same に直接渡せるんですね……。
わたしの半日はなんだったんだ\(^o^)/
@uskz さんありがとうございます。
とりあえず、リファレンス読んでくる。


[boost]
ver 1.45.0