5. Lambda expressions in details

ΥǤ͡ʷΦ˼ܤ롣 ġΥ֥ǤϤ줾ͭʦ˼ηˤĤƤ롣

5.1. Placeholders

BLL Ǥϡplaceholder1_typeplaceholder2_typeplaceholder3_typeȤ 3 ĤΥץ졼ۥƤ롣 ޤBLL ǤϤ줾Υץ졼ۥѿ_1, _2 and _3 򤢤餫Ƥ롣 桼ϤΥץ졼ۥѤʤȤ褤 ̤̾Υץ졼ۥϴñǤ롣 ץ졼ۥοѿФ褤 㤨СΤ褦ˤʤ롣

boost::lambda::placeholder1_type X;
boost::lambda::placeholder2_type Y;
boost::lambda::placeholder3_type Z;
ѿСX += Y * Z _1 += _2 * _3 Ǥ롣

˼ǤΥץ졼ۥλȤˤäơΦ˼ɽؿ̵ޤ롣 ΥǥåΥץ졼ۥˤοꤵ롣 㤨СΤ褦Ǥ롣

_1 + 5              // unary
_1 * _1 + _1        // unary
_1 + _2             // binary
bind(f, _1, _2, _3) // 3-ary
_3 + 10             // 3-ary
ǸιԤΦ˼ϻδؿ뤳ȤǤ롣 δؿϡ졢̵뤷 10 ä롣 ˡ˥ե󥯥Ϻ¤ΰ⤿ʤ ¿μºݤɬפʰ(ݡȤƤץ졼ۥοޤǤǤ)Ϳ뤳ȤǽǤ롣 ;ʰñ̵뤵Ǥ롣 㤨С
int i, j, k; 
_1(i, j, k)        // returns i, discards j and k
(_2 + _2)(i, j, k) // returns j+j, discards i and k
Ȥʤ롣 εǽطʤˤ߷ͳˤˤĤƤϡSection 1򸫤衣

黰ĤΥץ졼ۥ˲äơͤܤΥץ졼ۥ placeholderE_type ⤢롣 Υץ졼ۥλȤϡ˼Ǥ㳰 Section 5.7 Ƥ롣

°ץ졼ۥϤ줿Ȥѥ᥿ϤĤ⻲ȤˤäϤ롣 ϡץ졼ۥФ뤤ʤѤ°ȿǤ뤿Ǥ롣 㤨СΤ褦ˤʤ롣

int i = 1; 
(_1 += 2)(i);         // i is now 3
(++_1, cout << _1)(i) // i is now 4, outputs 4

5.2. Operator expressions

Ūʵ§ǤϡʤȤĤΦ˼Ȥ뤹٤Ƥ C++ α黻ҤθƽФϡ켫Ȥ˼Ǥ롣 Сɲǽʱ黻ҤΤۤȤɤϥݡȤƤ롣 㤨СʲΤΤͭʦ˼Ǥ롣

cout << _1, _2[_3] = _1 && false

Ĥ C++ α黻ҤΥСɤε§˴Ť¤ȡ̤ʾ¤롣

5.2.1. Operators that cannot be overloaded

Ĥα黻Ҥϴ˥Сɤ뤳ȤǤʤ(㤨С::, ., .*) ޤĤα黻Ҥ˴ؤƤϡ֤ͤη˴ؤ׷Τˡ˼뤿ΥСɤ򤹤뤳ȤǤʤ->., ->, new, new[], delete, delete[] and ?:(黻)ä黻ҤǤ롣

5.2.2. Assignment and subscript operators

ä黻Ҥϥ饹ΥдؿȤƼʤФʤʤ äơ黻Ҥκ¦ΰϦ˼ǤʤФʤʤ 㤨мΤ褦ˤʤ롣

int i; 
_1 = i;      // ok
i = _1;      // not ok. i is not a lambda expression
¤˴ؤñʲSection 5.5ˤ롣 ʷˤȡ ¦Υڥɤ Τ褦̤ʴؿ var ǥåפŪ˦˥ե󥯥ȤФ褤
var(i) = _1; // ok

5.2.3. Logical operators

黻Ҥûɾε§˽ 㤨СΥɤǤϡiϷ褷ƥ󥯥Ȥ뤳ȤϤʤ

bool flag = true; int i = 0;
(_1 || ++_2)(flag, i);

5.2.4. Comma operator

ޱ黻ҤϦ˼ʸζڤǤ롣 ޤϴؿƽФΰζڤǤ⤢뤿ᡢ;ʬʳ̤ɬפˤʤ뤳Ȥ롣 㤨СΤ褦ʤȤǤ롣

for_each(a.begin(), a.end(), (++_1, cout << _1));
++_1, cout << _1 Ϥ;ʬʳ̤ʤȡΥɤ for_each 4 ĤΰǸƽФȤƤȲᤵƤޤ

ޱ黻ҤѤƺ줿˥ե󥯥ϡΥڥɤɾƤ顢ΥڥɤɾȤ C++ ε§Ʊ褦ɾ롣 ˵󤲤Ǥϡa Ǥ줾Фơޤ󥯥Ȥ졢θǥȥ꡼ؽ񤭽Ф롣

5.2.5. Function call operator

ؿƽФ黻ҤˤϦ˥ե󥯥ɾ̤롣 ­ʤƽФϥѥΥ顼ȤƸФ롣

5.2.6. Member pointer operator

Хݥ󥿱黻 operator->* ϼͳ˥СɲǽǤ롣 äơ桼˴ؤƤϥХݥ󥿱黻Ҥ̤ʾϤʤ Ȥ߹߷ˤƤϤ⤦ʣǤ롣 ΰ륯饹 A Υ֥Ȥؤݥ󥿤Ǥꡢ¦ΰ A ΥФؤΥݥ󥿤Ǥ뤫A οƥ饹ΥФؤΥݥ󥿤ǤäˤϡȤ߹ߤΥХݥ󥿱黻ҤŬѤ롣 ˡĤξʬƹͤʤФʤʤ

  • ޤ¦ΰѿؤΥݥ󥿤ǤȤǤ롣 ξϡ˥ե󥯥ñ˼°ԤΥݥ󥿤ؤƤѿλȤ֤Ȥ߹ߤΥХݥ󥿱黻ҤƤФ롣 㤨СΤ褦ˤʤ롣

    struct A { int d; };
    A* a = new A();
      ...
    (a ->* &A::d);     // returns a reference to a->d 
    (_1 ->* &A::d)(a); // likewise
    

  • ˡ¦ΰдؿؤΥݥ󥿤ǤȤǤ롣 Τ褦Ȥ߹ߤα黻ҤθƽФϡΥдؿٱƽФΤ褦ʷ̤Ȥʤ롣 Τ褦ʼθˤϡдؿٱƽФΤΰꥹȤ³ʤƤϤʤʤ 㤨СΤ褦ˤʤ롣

    struct B { int foo(int); };
    B* b = new B();
      ...
    (b ->* &B::foo)         // returns a delayed call to b->foo
                            // a function argument list must follow
    (b ->* &B::foo)(1)      // ok, calls b->foo(1)
    
    (_1 ->* &B::foo)(b);    // returns a delayed call to b->foo, 
                            // no effect as such
    (_1 ->* &B::foo)(b)(1); // calls b->foo(1)
    

5.3. Bind expressions

bind ˤϼĤη롣

bind(target-function, bind-argument-list)
bind(target-member-function, object-argument, bind-argument-list)
bind ϴؿθƽФٱ䤵롣 ⤷target-function nδؿǤСbind-argument-list Ʊͤ n ĤΰޤǤʤФʤʤ ߤΥС BLL Ǥϡο n ˤϡ0 <= n <= 9 Ȥ¤롣 дؿŬѤˤϡоݤΥ֥ȤȤϤ뤿ᡢοϺ 8 ĤޤʤФʤʤ ʤץ졼ۥ֤뤳ȤǤ ˰Ū˸Ц˼֤뤳ȤǤȤȤС Ūˤ bind-argument-list ŪδؿؤͭʰΥꥹȤǤʤФʤʤ ޤŪδؿϦ˼ǤäƤ褤 bind η̤ϡ̵ޤϡδؿ֥ȤǤ롣 ΰοϡbind-argument-list Υץ졼ۥλȤˤäƷꤵ롣(ܤ Section 5.1 򸫤)

Ǽ褦ˡbind Ǻ줿˥ե󥯥֤ͤϡƥץ졼ȰȤŪ˻ꤹ뤳ȤǤ롣

bind<RET>(target-function, bind-argument-list)
ŪʻϡŪδؿ֤ͤηǤʤäΤɬפȤʤ롣

ʲΥ֥Ǥϡ͡ bind ηˤĤƤ롣

The following sections describe the different types of bind expressions.

5.3.1. Function pointers or references as targets

ŪδؿϡؿΥݥ󥿤ǤäƤ⻲ȤǤäƤ褯ޤδؿ«Ƥ⡢«ƤʤȤ褤 㤨С bind ͭǤ롣

X foo(A, B, C); A a; B b; C c;
bind(foo, _1, _2, c)(a, b);
bind(&foo, _1, _2, c)(a, b);
bind(_1, a, b, c)(foo);
֤ͤηοϤ bind ǤƲǤ롣

C++ ǤϥСɤ줿ؿΥɥ쥹ϡ Υɥ쥹ۣ椵ä줿ѿ˳Ƥ뤫 Τ褦ѿνȤƻѤ뤫 Ūʥ㥹ȤѤ줿Τ߼뤳ȤǤ롣 ĤޤꡢСɤ줿ؿϡ˼褦ľ bind ǻѤ뤳ȤϤǤʤ

void foo(int);
void foo(float);
int i; 
  ...
bind(&foo, _1)(i);                            // error 
  ...
void (*pf1)(int) = &foo;
bind(pf1, _1)(i);                             // ok
bind(static_cast<void(*)(int)>(&foo), _1)(i); // ok

5.3.2. Member functions as targets

bind ˤƥдؿؤΥݥ󥿤Ѥ뤿ʸˡϼ̤Ǥ롣 The syntax for using pointers to member function in bind expression is:

bind(target-member-function, object-argument, bind-argument-list)
֥ȤϡȤǤݥ󥿤Ǥ褤BLL ξξƱΥ󥿡եǥݡȤƤ롣
bool A::foo(int) const; 
A a;
vector<int> ints; 
  ...
find_if(ints.begin(), ints.end(), bind(&A::foo, a, _1)); 
find_if(ints.begin(), ints.end(), bind(&A::foo, &a, _1));
Ʊͤˡ֥Ȥ«ƤʤСbind η̤Φ˥ե󥯥ϼºݤϤ줿ݥ󥿤ȤˤäƤɤƤ֤ȤǤ롣ˤ򼨤
bool A::foo(int); 
list<A> refs; 
list<A*> pointers; 
  ...
find_if(refs.begin(), refs.end(), bind(&A::foo, _1, 1)); 
find_if(pointers.begin(), pointers.end(), bind(&A::foo, _1, 1));

󥿡եƱǤäƤ⡢֥Ȥݥ󥿤Ǥ뤫ȤǤ뤫ˤϡפʰ̣Ūʰ㤤롣ΰ㤤ϡؿ bind ΰμȡ«줿˥ե󥯥˳ǼˡˤΤǤ롣 ֥Ȥ¾ bind ΰƱͤϤ졢Ǽ롣(Section 4.4 ); Ĥޤꡢconst ʻȤȤϤ졢const ʥԡȤƦ˥ե󥯥˳Ǽ롣 ˤꡢ˥ե󥯥ȸΥдؿ䡢ܤˤƱ˥ե󥯥δ֤оƤޤ㤨СΤ褦ʾǤ롣

class A {
  int i; mutable int j;
public:

  A(int ii, int jj) : i(ii), j(jj) {};
  void set_i(int x) { i = x; }; 
  void set_j(int x) const { j = x; }; 
};
ݥ󥿤ȤƻѤ줿ˤϡư϶餯ץޤԤΤǤ롣
A a(0,0); int k = 1;
bind(&A::set_i, &a, _1)(k); // a.i == 1
bind(&A::set_j, &a, _1)(k); // a.j == 1
֥Ȥ const ʥԡǼƤȤƤ⡢Υ֥ aѹƤ롣 ϡ֥Ȥݥ󥿤ȤϤ줿Ǥꡢݥ󥿤ؤ֥Ȥԡ줿ΤǤϤʤݥ󥿼Ȥԡ줿Ǥ롣 ȤȤƻѤ줿ˤϡۤäưȤʤ롣
A a(0,0); int k = 1;
bind(&A::set_i, a, _1)(k); // error; a const copy of a is stored. 
                           // Cannot call a non-const function set_i
bind(&A::set_j, a, _1)(k); // a.j == 0, as a copy of a is modified

ԡȯɤˤϡΤ褦 ref cref ΥåѤѤФ褤(var constant_ref ƱͤǤ )

bind(&A::set_i, ref(a), _1)(k); // a.j == 1
bind(&A::set_j, cref(a), _1)(k); // a.j == 1

ޤǤλƤ«줿ˤΤߴط롣 ֥Ȥ«ƤʤˤϡϾ˻ȤȤϤ롣 äơĤΦ˥ե󥯥Ǥϡ a ϥԡʤ

A a(0,0);
bind(&A::set_i, _1, 1)(a); // a.i == 1
bind(&A::set_j, _1, 1)(a); // a.j == 1

5.3.3. Member variables as targets

ѿؤΥݥ󥿤ϼºݤˤϴؿǤϤʤ ˤؤ餺ؿ bind ˥ѿؤΥݥ󥿤뤳ȤǽǤ롣 Τ褦 bind ƽФȡΥѿλȤ֤롣 㤨СΤ褦ˤʤ롣

struct A { int data; };
A a;
bind(&A::data, _1)(a) = 1;     // a.data == 1
Ȥѿĥ֥Ȥ const/volatile νҤºŤ롣 㤨СǤ const ʰ֤ؽ񤭹⤦ȤƤ롣
const A ca = a;
bind(&A::data, _1)(ca) = 1;     // error

5.3.4. Function objects as targets

ؿ֥ȤŪδؿȤƻѤǤ롣 ؿ֥ȤȤϡؿƽФ黻Ҥ줿饹֥ȤΤȤǤ롣 ŪˤϡBLL Ǥդδؿ֥Ȥ֤ͤη뤳ȤϤǤʤ ؿ֥ȤΥ饹ѹäơBLL Ǥ褦ˤˡ롣

The sig template

BLL ؿ֥Ȥ֤ͤηǧ뤿ˤϡ type Ȥ֤ͤηꤹ typedef ä sig<Args> Хƥץ졼ȹ¤Τ󶡤ɬפ롣 줬ñǤ롣

struct A {
  template <class Args> struct sig { typedef B type; }
  B operator()(X, Y, Z); 
};
ƥץ졼Ȱ Args tuple(Τ˸Сcons ꥹ) [tuple] Ǥ롣 ơǽǤϴؿ֥ȼȤǤꡢĤǤϴؿ֥ȤƤФȤΰηǤ롣 ϡreturn_type typedef ǻꤹɸ饤֥δؿ֥Ȥ֤ͤηλͤӤȡɬװʾʣ˸뤫⤷ʤ ֤ͤηñ typedef ǼȡĤνפ¤ȯ롣
  1. ؿ֥ȤʣδؿƽФ黻ҤƤ硢Фۤʤ֤ͤηꤹˡʤ

  2. ؿƽФ黻Ҥƥץ졼ȤǤä硢֤ͤηϤΥƥץ졼Ȱ˰¸뤫⤷ʤ äơtypedef ƥץ졼Ȥˤɬפ롣C++ Ϥ򥵥ݡȤƤʤ

ʲΥɤϡ֤ͤηΰĤη˰¸Ǥꡢ sig ƥץ졼ȤˤäơɤΤ褦˰¸طɽǤ뤫򼨤Ƥ롣
struct A {

  // the return type equals the third argument type:
  template<class T1, T2, T3>
  T3 operator()(const T1& t1, const T2& t2, const T3& t3);

  template <class Args> 
  class sig {
    // get the third argument type (4th element)
    typedef typename 
      boost::tuples::element<3, Args>::type T3;
  public:
    typedef typename 
      boost::remove_cv<T3>::type type;
  }
};
Args ץǤϾ˻ȤǤʤǤ롣 ˡǤηϡconst volatile (ޤȤ const/volatile ) ޤϡξǽ뤳ȤǤ롣 ϡ const/volatile Ҥˤäơ֤ͤηرƶͿ뤳ȤǽǤ뤿Ǥ롣 ޤŪ const/volatile ˤäƽҤ줿ؿ֥ȤηȤ Args ץ˴ޤޤƤ뤳Ȥˤꡢؿ֥ȥ饹ϡconst const (ޤϡvolatile const volatile )δؿƽФ黻Ҥ򶦤˴ޤळȤǤġ줾ΰۤʤ֤ͤηȤ뤳ȤǽȤʤ롣

sig ƥץ졼ȤϰηΥץ뤫顢ηΰȤʤäƸƤФ줿֤ͤηؤ᥿ؿȸ뤳ȤǤ롣 ǼΤ褦ˡƥץ졼ȤϷɲʣˤʤäƤޤȤ롣 ŵŪʾ˼¹ԤΤϡץ뤫طΤ뷿Фꡢ const/volatile ҤȤäȤǤ롣 νȤʤʤˤĤƤϡBoost type_traits [type_traits] Tuple [type_traits] 饤֥򸫤衣 sig ƥץ졼ȤϺǽ FC++ 饤֥ [fc++] Ƴ줿ƱͤʻȤߤΤǤ롣

ΥСΥ饤֥Ǥϡɸ饤֥λͤǥեȤȤƤꡢ sig ƥץ졼Ȥǧ뤿ˤ̤ɬפǤä ߤ BLL Ǥϡ줬դˤʤäƤ롣 ɸ饤֥λͤ˽äե󥯥 bind ǻѤɬפȤΤˡstd_functor å 󶡤Ƥ롣 ΥåѤˤꡢresult_type typedef ˴Ťơؿ֥Ȥ sig ƥץ졼ȤѰդ롣 㤨СΤ褦ˤʤ롣

int i = 1;
bind(plus<int>(), _1, 1)(i);              // error, no sig template
bind(std_functor(plus<int>()), _1, 1)(i); // ok

5.4. Overriding the deduced return type

֤ͤηƥϰΥ桼α黻Ҥȥ饹֥Ȥޤ bind ֤ͤηǤʤ⤷ʤ ֤ͤηƥ򥪡С饤ɤ뤿ˡ̤ʦ˼η󶡤Ƥ롣 ˼ e ˥ե󥯥֤ͤ T ǤȼˤϡΤ褦˵ҤФ褤

ret<T>(e);
ˤꡢ˼ e ˤ֤ͤηڹԤʤΤˡT ֤ͤȤƻѤ롣 ˡT ˤǤդηǤ櫓ǤϤʤ Φ˥ե󥯥ηϰŪ T ѴǽǤʤФʤʤ 㤨СΤ褦ʤȤǤ롣
A a; B b;
C operator+(A, B);
int operator*(A, B); 
  ...
ret<D>(_1 + _2)(a, b);     // error (C cannot be converted to D)
ret<C>(_1 + _2)(a, b);     // ok
ret<float>(_1 * _2)(a, b); // ok (int can be converted to float)
  ...
struct X {
  Y operator(int)();   
};
  ...
X x; int i;
bind(x, _1)(i);            // error, return type cannot be deduced
ret<Y>(bind(x, _1))(i);    // ok
bind ˴ؤƤϡret ˻ѤǤؤɽ롣 κǸιԤϡΤ褦˵Ҥ뤳ȤǽǤ롣
bind<Z>(x, _1)(i);
εǽ Boost Bind library [bind] äΤǤ롣

ͥȤ˼ˤƤϡ ret ϤʤǤ֤ͤη˼Ԥ뤽줾ʬˤĤƻѤʤФʤʤ 㤨мΤ褦ʤȤǤ롣

A a; B b;
C operator+(A, B); D operator-(C);
  ...
ret<D>( - (_1 + _2))(a, b); // error 
ret<D>( - ret<C>(_1 + _2))(a, b); // ok

ret Ʊη˲٤ѤƤΤǤС ֤ͤηĥͤ롣 (ܤ Section 6 򸫤)

5.4.1. Nullary lambda functors and ret

ޤǤǼ褦ˡret ˤ֤ͤη¹Ԥ뤳ȤɤȤǤ롣 㳰⤢롣 C++ Υƥץ졼ȤΥ󥹥󥹲λȤߤΤˡ ѥ 0 Φ˥ե󥯥˴ؤƤϡƥץ졼Ȥμβ˺ݤ ơ֤ͤη롣 ˤꡢret ˤäȤ꤬ȯ롣 㤬褯ɽ路Ƥ롣

struct F { int operator()(int i) const; }; 
F f;
  ...
bind(f, _1);           // fails, cannot deduce the return type
ret<int>(bind(f, _1)); // ok
  ...
bind(f, 1);            // fails, cannot deduce the return type
ret<int>(bind(f, 1));  // fails as well!
BLL ϡ F typedef result_type Ƥʤᡢ Τ褦 bind θƽФ֤ͤη뤳ȤϤǤʤ ret 褷ƤȴԤ뤫⤷ʤ (κǸιԤΤ褦) bind η̤ǤʤΦ˥ե󥯥˴ؤƤϡޤǽʤΤǤ롣 ȤɬפǤäȤƤ⡢֤ͤηƥƥץ졼Ȥ󥹥󥹲롣 η̤Ȥƥѥ顼Ȥʤ롣

βˡϴؿ ret Ѥ뤳ȤǤϤʤΤ褦 bind θƽФˤơƥץ졼ȰŪ֤ͤηꤹ뤳ȤǤ롣

bind<int>(f, 1);       // ok
ret<T>(bind(arg-list)) 줿˥ե󥯥ȡbind<T>(arg-list) 줿˥ե󥯥Ʊεǽġ — ۤʤΤԤϰ̵Φ˥ե󥯥ˤƤޤưʤΤФԤϤξˤưȤȤǤ롣

5.5. Delaying constants and variables

ñؿ constant constant_ref var ϰ˥ե󥯥ؤѴΦ˥ե󥯥ϹԤ ĤѤǸΤΤѿѤ롣 ѿٱɾϡŪʦ˼ʸˡʤɬפȤʤ롣 󤲤ȡ

for_each(a.begin(), a.end(), cout << _1 << ' ');
for_each(a.begin(), a.end(), cout << ' ' << _1);
ǽιԤǤϡaǤǶڤäƽϤ뤬 ܤǤϡĶϤΤȤ˶ڤʤǡaǤϤ롣 ϡcout << ' ' ȤΥڥɤΤ˼ǤʤǤ롣 äơcout << ' ' Ȥ¨¤ɾƤޤΤǤ롣 cout << ' ' Ȥٱɾ뤿ˤϡڥɤΰĤ˼ǤŪ˼ʤƤϤʤʤ ϡؿ constant ˤäƹԤʤ롣
for_each(a.begin(), a.end(), cout << constant(' ') << _1);
constant(' ')θƽФˤꡢ̵Φ˥ե󥯥롣 Υե󥯥ϡʸ' 'ǼƽФ줿ȤˤʸؤλȤ֤ ؿ constant_ref ⡢Τؤ const ʻȤǼȤơƱͤǤ롣 constant constant_ref Ͼ嵭Τ褦ˡ黻ҤθƽФѤȤˤΤɬפȤʤ롣

ѿɾٱ䤵ɬפ롣 ƥʤǤֹդꥹȤȤƽϤȤ롣

int index = 0; 
for_each(a.begin(), a.end(), cout << ++index << ':' << _1 << '\n');
for_each(a.begin(), a.end(), cout << ++var(index) << ':' << _1 << '\n');
ǽιԤ for_each θƽФϴ̤ˤưʤ index ϰ٤󥯥Ȥ졢ͤ٤ϥȥ꡼˽񤭽Ф롣 var Ѥơindex ˼Ȥ뤳Ȥˤꡢ˾̤롣

ޤȤȡvar(x) ѿ xؤλȤǼ̵Φ˥ե󥯥롣 Φ˥ե󥯥ƽФȡx ؤλȤ֤롣

Naming delayed constants and variables

˼γ¦ٱɾѿä̾դ뤳ȤǽǤ롣 ƥץ졼 var_type constant_type constant_ref_type ϤŪΤ󶡤Ƥ롣 ϼΤ褦˻Ѥ롣

var_type<T>::type delayed_i(var(i));
constant_type<T>::type delayed_c(constant(c));
ǽιԤǤϡ T ѿ i ٱɾѤ delayed_i ȤƤ롣 ƱͤˡܤǤϡ c ٱɾѤ delayed_c ȤƤ롣 㤨С
int i = 0; int j;
for_each(a.begin(), a.end(), (var(j) = _1, _1 = var(i), var(i) = var(j))); 
ϼΤΤǤ롣
int i = 0; int j;
var_type<int>::type vi(var(i)), vj(var(j));
for_each(a.begin(), a.end(), (vj = _1, _1 = vi, vi = vj));

ٱɾ̾դ󤲤ȡ

constant_type<char>::type space(constant(' '));
for_each(a.begin(),a.end(), cout << space << _1);

About assignment and subscript operators

Section 5.2.2 Ǽ褦ˡźα黻ҤϾ˥дؿȤ롣 Τᡢ x = y x[y] ημ˼Ȳᤵ뤿ˤϡ¦ΥڥɤϦ˼ǤʤФʤʤ ̤Ȥơvar򤳤ŪΤ˻ѤʤФʤʤ礬롣 ˡSection 5.2.2ƤӼ

int i; 
i = _1;       // error
var(i) = _1;  // ok

+= -= Ȥäʣ黻ҤдؿȤ뤳ȤǽǤ롣ΤᡢȤ¦ΥڥɤΤߤ˼ǤäȤƤ⡢μϦ˼ȤƲᤵ롣 ʤ顢¦ΥڥɤŪٱɾƤʤ 㤨Сi += _1 var(i) += _1 Ǥ롣

5.6. Lambda expressions for control structures

BLL 湽¤ɽ˥ե󥯥뤤ĤδؿƤ롣 ϡȤƦ˥ե󥯤ꡢ֤ͤ void Ǥ롣 ޤ󼨤롣ʲΥɤϤ륳ƥ aζǤ򤹤٤ƽϤ롣

for_each(a.begin(), a.end(), 
         if_then(_1 % 2 == 0, cout << _1));  

BLL 湽¤Τ˰ʲδؿƥץ졼Ȥ򥵥ݡȤ롣

if_then(condition, then_part)
if_then_else(condition, then_part, else_part)
if_then_else_return(condition, then_part, else_part)
while_loop(condition, body)
while_loop(condition) // no body case
do_while_loop(condition, body)
do_while_loop(condition) // no body case 
for_loop(init, condition, increment, body)
for_loop(init, condition, increment) // no body case
switch_statement(...)
٤Ƥ湽¤Φ˥ե󥯥֤ͤ voidǤ롣 㳰ϡξ黻ҤθƽФåפ if_then_else_return Ǥ롣
condition ? then_part : else_part
α黻Ҥ֤ͤηε§ϾʣǤ롣 Ūˤϡξʬη̤ηƱǤСη֤ͤηǤ롣 ʬηη̤ۤʤΤǤС ʬη̡㤨 A Ϥ⤦Ĥʬη̡㤨 B ѴǽǤʤФʤʤ Τ褦ʾǤϡ֤ͤη BǤ롣 ˡ̤ηͤǤС֤ͤ⺸ͤˤʤǤ

ٱɾѿϡ湽¤Φ˼ˤ褯롣 㤨СǤϡfor_loop ΰ˼Ѵ뤿 varѤƤ롣 Υɤ󼡸γǤ 1 äΤǤ롣

int a[5][10]; int i;
for_each(a, a+5, 
  for_loop(var(i)=0, var(i)<10, ++var(i), 
           _1[var(i)] += 1));  

BLL Joel de Guzmann Ƥ̤漰ʸˡ⥵ݡȤƤ롣 operator[] 򥪡Сɤ뤳Ȥˤꡢ Ȥ߹ߤ湽¤ˤ褯Τ¸Ǥ롣

if_(condition)[then_part]
if_(condition)[then_part].else_[else_part]
while_(condition)[body]
do_[body].while_(condition)
for_(init, condition, increment)[body]
㤨СʸˡѤ ۤɤ if_then ϼΤ褦˵Ҥ뤳ȤǤ롣
for_each(a.begin(), a.end(), 
         if(_1 % 2 == 0)[ cout << _1 ])  
ηиˤäƤϡΤĤ侩ʤʤ뤫⤷ʤ

5.6.1. Switch statement

case ʸѸĤǤ뤿ᡢ switch ʸ湽¤Φ˼Ϥ⤦ʣǤ롣 Ū switch ʸΦ˼ηϼΤ褦ˤʤ롣

switch_statement(condition, 
  case_statement<label>(lambda expression),
  case_statement<label>(lambda expression),
  ...
  default_statement(lambda expression)
)
condition ϡ ֤ͤηΦ˥ե󥯥˼ǤʤФʤʤ ؿ case_statement ˤäƳ case ʸ졢 ؿ default_statement ˤäƥץǤ default ʸ롣 case ʸΥ٥ϴؿ case_statement ؤΥƥץ졼ȰˤäŪ˻ꤵ졢break ʸϰŪ˳ case ʸ˴ޤޤƤ롣 㤨Сa ˥ե󥯥ǤȤơcase_statement<1>(a) ϼΤ褦ʥɤ롣
case 1: 
  evaluate lambda functor a; 
  break;
ؿ switch_statement Ϻ 9 Ĥ case ʸĤȤǤ롣

switch ʸδ򼨤 ΥɤǤϡ륳ƥ v γǤФơ0 Ǥ “zero” 1 Ǥ “one” 򡢤¾ο n ФƤϡ“other: n” ȤʸϤ롣 Ǥθ˲ԤϤ뤿ˡswitch_statement θ̤ʦ˼³Ƥ롣

std::for_each(v.begin(), v.end(),
  ( 
    switch_statement(
      _1,
      case_statement<0>(std::cout << constant("zero")),
      case_statement<1>(std::cout << constant("one")),
      default_statement(cout << constant("other: ") << _1)
    ), 
    cout << constant("\n") 
  )
);

5.7. Exceptions

BLL 㳰Фꡢª˥ե󥯥󶡤Ƥ롣 㳰Ф˥ե󥯥ñؿ throw_exception ˤä롣 δؿΰФ㳰Ф㳰˥ե󥯥Ǥ롣 㳰Ф˥ե󥯥ϡ̵ؿ rethrow ˤä롣

㳰ϥɥΦ˼Ϥ⤦ʣǤ롣 try-catch ֥åΦ˼ΰ̷ϼΤ褦ˤʤ롣

try_catch(
  lambda expression,
  catch_exception<type>(lambda expression),
  catch_exception<type>(lambda expression),
  ...
  catch_all(lambda expression)
)
ǽΦ˼ try ֥åǤ롣 catch_exception ª㳰ηƥץ졼ȰȤŪ˻ꤷ catch ֥å롣 catch_exception Φ˼Ǥϡ㳰ªݤư롣 ʤ㳰ϥɥ㳰򻲾ȤȤª뤳Ȥˤʤ롣 ʤcatch_exception<T>(...) Ȥ˼ϼΤ褦 catch ֥åȤʤ롣
catch(T& e) { ... }
Ǹ catch ֥åϡcatch_exception<type> ˡcatch_all θƽФȤƤ褤 catch(...) Φ˼Ǥ롣

Example 1 Ǥ BLL 㳰εǽλȤμ򼨤Ƥ롣 ǽ㳰ϥɥ foo_exception 㳰­롣 ץ졼ۥ _1 ϥɥǻѤƤ롣

ܤ㳰ϥɥǤϡ㳰Фˡȡ 㳰ץ졼ۥ _e μ򼨤Ƥ롣 ̤ʥץ졼ۥϡ­㳰֥Ȥϥɥ黲ȤƤ롣 Ǥϡ㳰θʸտ路Ƥ std::exception 㳰򰷤äƤ롣 ̵Υдؿ what ˤФȤǤ롣 bind(&std::exception::what, _e) ȤϤδؿƽФ˥ե󥯥롣 _e 㳰ϥɥ򼨤˼γ¦ǤϻѤǤʤ ܤ㳰ϥɥκǸιԤǤϡ㳰֥Ȥۤ ؿ throw_exception Ѥơ㳰֥ȤФ롣 ˼ˤ롢֥Ȥιۤ˴˴ؤƤϡ Section 5.8 ˤ롣

ơܤ㳰ϥɥ(catch_all)Ǥϡ㳰κФμ򼨤

Example 1. Throwing and handling exceptions in lambda expressions.

for_each(
  a.begin(), a.end(),
  try_catch(
    bind(foo, _1),                 // foo may throw
    catch_exception<foo_exception>(
      cout << constant("Caught foo_exception: ") 
           << "foo was called with argument = " << _1
    ),
    catch_exception<std::exception>(
      cout << constant("Caught std::exception: ") 
           << bind(&std::exception::what, _e),
      throw_exception(bind(constructor<bar_exception>(), _1)))
    ),      
    catch_all(
      (cout << constant("Unknown"), rethrow())
    )
  )
);

5.8. Construction and destruction

new delete ϥСɲǽǤ뤬 ֤ͤͽޤäƤ롣 äˡ֤ͤ˥ե󥯥Ȥ뤳ȤϤǤʤ Τᡢ˼Τ˥Сɤ뤳ȤϤʤ 󥹥ȥ饯Υɥ쥹뤳ȤϤǤʤ äơ󥹥ȥ饯 bind оݤȤƻѤ뤳ȤϤǤʤ ΤȤϡǥȥ饯˴ؤƤƱǤ롣 Τ褦¤򤹤뤿ˡBLL 󥹥ȥ饯ǥȥ饯Ʊͤ new delete θƽФԤʤΥåѤΥ饹 Ƥ롣 Υ饹Υ󥹥󥹤ϴؿ֥ȤǤꡢ bind оݤȤƻѤ뤳ȤǽǤ롣 󤲤롣

int* a[10];
for_each(a, a+10, _1 = bind(new_ptr<int>())); 
for_each(a, a+10, bind(delete_ptr(), _1));
new_ptr<int>() Ȥϡ ƽФ줿Ȥˡnew int()ƽФؿ֥Ȥ롣 ơbind ˤθƽФåפ뤳Ȥˤꡢ δؿ֥奯Ȥ˥ե󥯥ȤƤ롣 Ʊͤˡdelete_ptr() ȤϰФơdelete ƽФؿ֥Ȥ롣 new_ptr<T>() Ʊͤ˰뤳ȤǤ ΰľܥ󥹥ȥ饯θƽФϤ롣 ˤꡢȤ륳󥹥ȥ饯θƽФǽˤʤ롣

˼ˤ륳󥹥ȥ饯򼨤 ʲΥɤǤϡĤΥƥ x y Ф pair ۤܤΥƥʤ롣

vector<pair<int, int> > v;
transform(x.begin(), x.end(), y.begin(), back_inserter(v),
          bind(constructor<pair<int, int> >(), _1, _2));
Table 1 ˥֥Ȥιۤ˴˴ؤ뤹٤Ƥδؿ֥ȤޤȤ᤿ ɽϡؿ֥ȤȸƽФμȤμɾθ̤򼨤Ƥ롣

Table 1. Construction and destruction related function objects.

Function object call Wrapped expression
constructor<T>()(arg_list) T(arg_list)
destructor()(a) a.~A(), where a is of type A
destructor()(pa) pa.->A(), where pa is of type A*
new_ptr<T>()(arg_list) new T(arg_list)
new_array<T>()(sz) new T[sz]
delete_ptr()(p) delete p
delete_array()(p) delete p[]

5.9. Special lambda expressions

5.9.1. Preventing argument substitution

˥ե󥯥ƽФ줿ȤǥեȤưǤϡ٤ƤʬˤƼ°ץ졼ۥ֤롣 Υ֥Ǥϡ֤ʬɾɤˡ򼨤 ɤΤ褦ʤȤˡεǽȤ٤롣

bind ΰˤǤդΦ˼ꤹ뤳ȤǤ롣 㤨СΤ褦̤ bind ȤʤäƤ褤

int foo(int); int bar(int);
...
int i;
bind(foo, bind(bar, _1)(i);
ǸιԤǤϡfoo(bar(i)); ƽФ롣 bind Ĥޤоݤδؿ㳰ǤϤʤ bind ϡbind ǤäƤ褤 ¦Φ˥ե󥯥ϡ̤ʦ˥ե󥯥ؿݥ󥿡дؿؤΥݥ󥿤ȤäоݤδؿȤƻѤΤñ֤Ф褤 㤨мΥɤǤϡ¦Φ˥ե󥯥ĤδؿΤĤ򤷡 δؿؤΥݥ󥿤֤
int add(int a, int b) { return a+b; }
int mul(int a, int b) { return a*b; }
int(*)(int, int)  add_or_mul(bool x) { 
  return x ? add : mul; 
}

bool condition; int i; int j;
...
bind(bind(&add_or_mul, _1), _2, _3)(condition, i, j);

5.9.1.1. Unlambda

оݤδؿƥץ졼Ȱ˰¸ѿǤˤϡ ĤΤޤˤ bind ͥȤƤޤȤ롣 Ūоݤδؿϴؿƥץ졼ȤβȤʤꤦ롣 Τ褦ʾˤϡץޤоݤδؿ˥ե󥯥ɤΤʤ⤷ʤ

δؿƥץ졼ȤͤƤߤ롣

template<class F>
int nested(const F& f) {
  int x;
  ...
  bind(f, _1)(x);
  ...
}
δؿΤǡ f bind оݤδؿȤѤƤ롣 bind θƽФͭǤ뤿ˤϡ f ñؿǤʤФʤʤ ʲĤ nested θƽФͤƤߤ롣
int foo(int);
int bar(int, int);
nested(&foo);
nested(bind(bar, 1, _1));
ξȤñδؿޤϴؿ֥ȤǤꡢŬڤʰ֤ͤġ ԤϥѥǤʤ ԤθƽФˤƤϡnested bind ϼΤ褦ˤʤäƤޤ
bind(bind(bar, 1, _1), _1) 
x ȤäƸƽФ줿Ȥ ִ졢ɤϼΤ褦˸ƽФȤȤʤ롣
bar(1, x)(x)
ϡ顼Ȥʤ롣 bar θƽФ֤ͤ int Ǥꡢ ñδؿؿ֥ȤǤϤʤ

嵭Ǥϡnested bind ΰտޤ f ˥ե󥯥ǤϤʤ̾δؿ֥ȤȤưȤǤ롣 BLL ϴؿƥץ졼 unlambda 󶡤Ƥ롣 δؿƥץ졼Ȥˤꡢ unlambda ˥åפ줿˥ե󥯥ϤϤ˥ե󥯥ǤϤʤΥץˤϴطʤ ȤȤɽ롣 ˥ե󥯥ʳηΰФƤϡunlambda const ʥ֥Ȥ const ѹ뤳ȤơǤ롣

unlambda Ѥơ ؿ nested ϼΤ褦˽񤯤ȤǤ롣

template<class F>
int nested(const F& f) {
  int x;
  ...
  bind(unlambda(f), _1)(x);
  ...
}

5.9.1.2. Protect

ؿ protect unlambda ȴط롣 δؿɤѤ롣 unlambda Ϧ˥ե󥯥³Ū̾δؿ֥ȤѴΤФơprotected Ϥɾ˰Ū˹Ԥ 򼨤

int x = 1, y = 10;
(_1 + protect(_1 + 2))(x)(y);
ǽθƽФǤϡx Ǻ _1 졢 η̤̤ʦ˥ե󥯥 x + (_1 + 2) Ȥʤ롣 Φ˥ե󥯥 y ȤȤ˸ƽФȡ x + (y + 2) ȤʤꡢǽŪˤ 13 Ȥʤ롣

protected 饤֥˴ޤ᤿פưϥͥȤ STL 르ꥺθƽФǽˤ뤳ȤǤä (Section 5.11)

5.9.2. Rvalues as actual arguments to lambda functors

const ʱͤ˥ե󥯥μ°Ȥʤ뤳ȤϤǤʤ ϽϹͤ줿߷׾ηΤǤ롣 ¤ʤС°ФѤͿʤȤǤ롣 ¤򤹤ˡ롣 ֥ Section 4.3 ƤӻѤơĤβ¤٤롣

int i = 1; int j = 2; 
(_1 + _2)(i, j); // ok
(_1 + _2)(1, 2); // error (!)
  1. ⤷ͤ饹ǤСͤؿ֤ͤη const Ȥ٤Ǥ롣 ͤ¤ˤꡢǰʤ餳ˡȤ߹ߤηФƤϤޤʤ Ȥ߹ߤηαͤϡconst 뤳ȤǤʤǤ롣

  2. ˴ؿθƽФʬѹǤΤǤС ؿ make_const ѤƱͤ const 뤳ȤǤ롣 򼨤

    (_1 + _2)(make_const(1), make_const(2)); // ok
    
    Ū˦˴ؿθƽФɸॢ르ꥺΥƥץ졼ȴؿǹԤ뤿ᡢβѤ뤳Ȥ񤷤

  3. 嵭Τ⤬ԲǽǤС˼ ؿconst_parameters åפ뤳ȤǤ롣 δؿϰ const ȤȤƤȤ̤ηΦ˥ե󥯥롣 ʲ򼨤

    const_parameters(_1 + _2)(1, 2); // ok
    
    const_parameters Ƥΰ const ʷˤ롣 ΤᡢΰĤ const ʱͤǤꡢ ̤ʰ const ʻȤȤϤˤϤˡϻѤǤʤ

  4. ʾΤŤԲǽǤˤĤβ¸ߤ롣 ˡϻǰʤ const ˤ뤳ȤǽȤʤäƤޤ βˡϤ̤ʦ˥ե󥯥ΥåѤѤ뤳ȤǤ롣 ΥåѤˤ break_const ̾դơ桼ˤδؿŪʴդ¥Ƥ롣 ؿ break_const const Ȥưꡢåפ줿˥ե󥯥ƽФ const ΤƵ˥ե󥯥롣 򼨤

    int i; 
    ...
    (_1 += _2)(i, 2);                 // error, 2 is a non-const rvalue
    const_parameters(_1 += _2)(i, 2); // error, i becomes const
    break_const(_1 += _2)(i, 2);      // ok, but dangerous
    
    break_const const_parameters η̤Ϧ˥ե󥯥ǤϤʤΤᡢ㤨мΤ褦ˡ˼ʬȤƻѤ뤳ȤϤǤʤ
    break_const(_1 + _2) + _3; // fails.
    const_parameters(_1 + _2) + _3; // fails.
    
    ʬŪʦ˥ե󥯥 BLL ǸƽФ졢 const ʱͤαƶʤᡢ μΥɤɬפȤ뤳ȤϤʤ

5.10. Casts, sizeof and typeid

5.10.1. Cast expressions

BLL static_castdynamic_casy const_castreinterpret_cast ͤĤΥ㥹ȤƱʤΤƤ롣 BLL Υ㥹Ȥˤϡll_ ȤƬդƤ롣 㥹ηϥƥץ졼ȰȤŪ˻ꤷ ͣΰϥ㥹ȤԤʤǤ롣 ˥ե󥯥ǤС˥ե󥯥ޤɾ롣 㤨СʲΥɤǤϡll_dynamic_cast Ѥơ ƥ a derived Υ󥹥󥹤ο롣

class base {};
class derived : public base {};

vector<base*> a;
...
int count = 0;
for_each(a.begin(), a.end(), 
         if_then(ll_dynamic_cast<derived*>(_1), ++var(count)));

5.10.2. Sizeof and typeid

BLL sizeof typeid ƱʤΤϡ ll_sizeof ll_typeid ̾դƤ롣 ȤĤΰȤ롣ΰϦ˼Ǥ褤 ˤ줿˥ե󥯥ϡsizeof typeid θƽФåפ롣ơ˥ե󥯥ƽФ줿Ȥˡ åפ줿¹Ԥ롣 ʲ򼨤

vector<base*> a; 
...
for_each(a.begin(), a.end(), 
         cout << bind(&type_info::name, ll_typeid(*_1)));
ll_typeid ϳǤФơtypeid ƽФ˥ե󥯥롣 typeid θƽФη̤ type_info 饹 󥹥󥹤Ǥꡢbind ϤΥдؿ name Ƥ ˥ե󥯥롣

5.11. Nesting STL algorithm invocations

BLL STL 르ꥺΤ褯ȤΤ򡢴ؿ֥ȥ饹ȤƤꡢ Υ󥹥󥹤 bind оݤδؿȤƻѤǤ롣 㤨СʲΥɤǤϡ󼡸Ǥȿơ¤׻롣

int a[100][200];
int sum = 0;

std::for_each(a, a + 100, 
	      bind(ll::for_each(), _1, _1 + 200, protect(sum += _1)));
BLL STL 르ꥺϥ饹Ǥ롣 Υ饹ǤϡؿƽФ黻(ˤϥСɤ) std ֤̾бؿƥץ졼ȤƽФ褦ˤƤ롣 餹٤Ƥι¤Τʬ̾ boost::lambda::ll ¸ߤ롣

˼ˤ륪Сɤ줿дؿθƽФɽñˡϤʤ ΤȤˤꡢͥȤ STL 르ꥺͭ¤Ƥޤ 㤨Сƥץ졼ȥƥʤˤơؿ begin Сɤ줿İʾ夢롣 ŪˤϡʲεɤΤ񤯤ȤϤǤʤ

std::for_each(a.begin(), a.end(), 
	      bind(ll::for_each(), _1.begin(), _1.end(), protect(sum += _1)));
褯ξˤб󶡤Ƥ롣 BLL call_begin call_end ȤĤΥإѴؿ֥ȥ饹Ƥ롣 Υ饹Ϥ줾쥳ƥʤδؿ begin ȴؿ end θƽФåפƥʤ const_iterator ֤ Υإѥƥץ졼ȤѤȡ嵭ΥɤϼΤ褦ˤʤ롣
std::for_each(a.begin(), a.end(), 
	      bind(ll::for_each(), 
                   bind(call_begin(), _1), bind(call_end(), _1),
                        protect(sum += _1)));