#include <boost/spirit/typeof/typeof.hpp> // このヘッダはBoostには #include <boost/spirit/typeof/type_encoding.hpp> // 入っていません. #include <boost/spirit/typeof/template_encoding.hpp> // 下を参照. #include <vector> #include <utility> #include <iostream> #include <algorithm> #include <cstdlib> #include <boost/lambda/lambda.hpp> #include <boost/lambda/bind.hpp> #include <boost/lambda/if.hpp> #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() // for std::pair BOOST_TYPEOF_REGISTER_TEMPLATE(std::pair, 2); // for std::basic_ostream BOOST_TYPEOF_REGISTER_TEMPLATE(std::basic_ostream, 2); BOOST_TYPEOF_REGISTER_TEMPLATE(std::char_traits, 1); // for boost::lambda BOOST_TYPEOF_REGISTER_TEMPLATE(boost::tuples::tuple, 2); BOOST_TYPEOF_REGISTER_TYPE(boost::tuples::null_type); BOOST_TYPEOF_REGISTER_TEMPLATE(boost::lambda::lambda_functor, 1); BOOST_TYPEOF_REGISTER_TEMPLATE(boost::lambda::lambda_functor_base, 2); // for boost::lambda::unlambda BOOST_TYPEOF_REGISTER_TEMPLATE(boost::lambda::non_lambda_functor, 1); // for boost::lambda::bind BOOST_TYPEOF_REGISTER_TEMPLATE_X(boost::lambda::action, (int)(class)); BOOST_TYPEOF_REGISTER_TEMPLATE_X(boost::lambda::function_action, (int)(class)); BOOST_TYPEOF_REGISTER_TYPE(boost::lambda::detail::unspecified); // for arithmetic action BOOST_TYPEOF_REGISTER_TEMPLATE(boost::lambda::arithmetic_action, 1); BOOST_TYPEOF_REGISTER_TYPE(boost::lambda::multiply_action); BOOST_TYPEOF_REGISTER_TYPE(boost::lambda::remainder_action); // for relational_action BOOST_TYPEOF_REGISTER_TEMPLATE(boost::lambda::relational_action, 1); BOOST_TYPEOF_REGISTER_TYPE(boost::lambda::less_action); BOOST_TYPEOF_REGISTER_TYPE(boost::lambda::equal_action); // for bitwise action BOOST_TYPEOF_REGISTER_TEMPLATE(boost::lambda::bitwise_action, 1); BOOST_TYPEOF_REGISTER_TYPE(boost::lambda::leftshift_action); // for place holder BOOST_TYPEOF_REGISTER_TYPE(boost::lambda::placeholder<1>); BOOST_TYPEOF_REGISTER_TYPE(boost::lambda::placeholder<2>); struct X { int i; int j; }; std::ostream &operator<<(std::ostream &os, X const &x) { return os << '(' << x.i << ',' << x.j << ')'; } BOOST_TYPEOF_REGISTER_TYPE(X); #define LOCAL_FUNCTOR(name, expr) BOOST_AUTO(name, boost::lambda::unlambda(expr)) int main() { using namespace std; using namespace boost::lambda; BOOST_AUTO(p, make_pair(make_pair(5, 3.14159), make_pair(2.71828, 6))); LOCAL_FUNCTOR(print, cout << _1 << '\n'); print(p.first.first); print(p.first.second); print(p.second.first); print(p.second.second); print(""); vector<int> v(10); { // vに1,2,3,...を詰める int i = 1; generate(v.begin(), v.end(), var(i)++); } LOCAL_FUNCTOR(is_even, _1 % 2 == 0); LOCAL_FUNCTOR(square, _1 * _1); // 偶数だけ2乗 for_each(v.begin(), v.end(), if_(bind(is_even, _1))[_1 = bind(square, _1)]); for_each(v.begin(), v.end(), bind(print, _1)); print(""); // 奇数だけ2乗 for_each(v.begin(), v.end(), if_(!bind(is_even, _1))[_1 = bind(square, _1)]); for_each(v.begin(), v.end(), bind(print, _1)); print(""); LOCAL_FUNCTOR(as_i, bind(&X::i, _1)); LOCAL_FUNCTOR(as_j, bind(&X::j, _1)); vector<X> xs(10); // xsの各要素のメンバを乱数で詰める for_each(xs.begin(), xs.end(), (bind(as_i, _1) = bind(rand), bind(as_j, _1) = bind(rand))); // xsの各要素を出力 for_each(xs.begin(), xs.end(), print(_1)); print(""); // メンバ変数iについてソート sort(xs.begin(), xs.end(), bind(as_i, _1) < bind(as_i, _2)); for_each(xs.begin(), xs.end(), print(_1)); print(""); // メンバ変数jについてソート sort(xs.begin(), xs.end(), bind(as_j, _1) < bind(as_j, _2)); for_each(xs.begin(), xs.end(), print(_1)); print(""); }
なんていうのかな・・・.なんだろう・・・.何コレ?('A`)
lambda式を名前付きにすると,unlambda/protect等の特殊な問題が表面化しやすいものの,概してヤヴァい.
#しばらく使ってるうちに,unlambdaをかけたものを名前付けして使うときにbindするが直感的だと気づいた.というか,この使い方はまさに名前付き関数内ファンクタの生成.varでローカル変数を参照できるわ,汎用アルゴリズムに突っ込めるわ,インライン化可能だわで当初に想像していたよりも遥かに凶悪な代物だ・・・.
ちなみに上で使っているtypeofエミュレーションの実装は以下の記事経由で取ってきたもの.
http://lists.boost.org/MailArchives/boost/msg70583.php