typeof + Boost.Lambda

#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