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