Phoenix.bind VS Lambda.bind

Hi, Now I'm looking at Phoenix and Lambda libraries. Could somebody explain why Lambda allows to use the following expression: void foo(int) { ... } ... bind(foo, _1)(10); yet Phoenix does not. Phoenix requires to use helper variable: void foo(int) { ... } ... int i = 0; bind(foo, _1)(i); I've read document about "Forwarding Function Problem" (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm). I understand the core issue, but how does Lambda.bind solve it? Thank you, Alexey.

Alexey Tkachenko wrote:
Hi, Now I'm looking at Phoenix and Lambda libraries. Could somebody explain why Lambda allows to use the following expression: void foo(int) { ... } ... bind(foo, _1)(10);
yet Phoenix does not. Phoenix requires to use helper variable: void foo(int) { ... } ... int i = 0; bind(foo, _1)(i);
I've read document about "Forwarding Function Problem" (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm). I understand the core issue, but how does Lambda.bind solve it?
Lambda takes by value, Phoenix takes by reference.

Hi, Now I'm looking at Phoenix and Lambda libraries. Could somebody explain why Lambda allows to use the following expression: void foo(int) { ... } ... bind(foo, _1)(10);
yet Phoenix does not. Phoenix requires to use helper variable: void foo(int) { ... } ... int i = 0; bind(foo, _1)(i);
I've read document about "Forwarding Function Problem" (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm). I understand the core issue, but how does Lambda.bind solve it?
Lambda takes by value, Phoenix takes by reference.
Both Lambda and Phoenix pass arguments by reference or by const reference. Moreover if I write following code it compiles fine: int add(int a, int b) { return a + b; } void bind_expression() { const int i = 5; cout << bind(add, _1, _2)(i, i) << endl; cout << bind(add, _1, _2)((const int&)10, i) << endl; } But if I change second 'bind' to (type cast is removed): cout << bind(add, _1, _2)(10, i) << endl; compilation failes. For me it's kind of magic. I use boost 1.39 and my compiler - g++ 4.3.1 Regards, Alexey.

On Fri, Apr 9, 2010 at 6:43 PM, Alexey Tkachenko [snip]
Both Lambda and Phoenix pass arguments by reference or by const reference.
IIRC lambda does perfect forwarding up to 3 arguments (i.e. it has overloads for all const and non const combinations up to 3 args). Phoenix does not: it takes its parameters by non const reference.
Moreover if I write following code it compiles fine: int add(int a, int b) { return a + b; } void bind_expression() { const int i = 5; cout << bind(add, _1, _2)(i, i) << endl; cout << bind(add, _1, _2)((const int&)10, i) << endl; } But if I change second 'bind' to (type cast is removed): cout << bind(add, _1, _2)(10, i) << endl; compilation failes.
For me it's kind of magic. I use boost 1.39 and my compiler - g++ 4.3.1
By explicitly casting to const int&, I think that, for the expression: bind(add, _1, _2)((const int&)10, i) T1 is deduced as const in for template <class T1, class T2> operator()(T1&, T2&) forming a const reference that can bind to the temporary. I had never realized that the cast would have worked! HTH, -- gpd

On Fri, Apr 9, 2010 at 11:55 AM, Giovanni Piero Deretta <gpderetta@gmail.com> wrote:
On Fri, Apr 9, 2010 at 6:43 PM, Alexey Tkachenko [snip]
Both Lambda and Phoenix pass arguments by reference or by const reference.
IIRC lambda does perfect forwarding up to 3 arguments (i.e. it has overloads for all const and non const combinations up to 3 args).
Phoenix does not: it takes its parameters by non const reference.
Moreover if I write following code it compiles fine: int add(int a, int b) { return a + b; } void bind_expression() { const int i = 5; cout << bind(add, _1, _2)(i, i) << endl; cout << bind(add, _1, _2)((const int&)10, i) << endl; } But if I change second 'bind' to (type cast is removed): cout << bind(add, _1, _2)(10, i) << endl; compilation failes.
For me it's kind of magic. I use boost 1.39 and my compiler - g++ 4.3.1
By explicitly casting to const int&, I think that, for the expression:
bind(add, _1, _2)((const int&)10, i)
T1 is deduced as const in for
template <class T1, class T2> operator()(T1&, T2&)
forming a const reference that can bind to the temporary. I had never realized that the cast would have worked!
For note, I think it is expected for the new Phoenix v3 to use the Functional.Forwarding adapters to fix that bug up to any number (not just 3 or so) of arguments.
participants (4)
-
Alexey Tkachenko
-
Giovanni Piero Deretta
-
Mathias Gaunard
-
OvermindDL1