From: Helmut Jarausch on
Hi,

how can I declare a function which takes a lambda-expression.
Naively, I tried


// compile with gcc-4.5 -std=c++0x

#include <iostream>
using std::cout; using std::cerr; using std::cin; using std::endl;

void calc(double x, double CVT(double)) {
cout << "\nresult= " << CVT(x) << endl;
}

int main() {
double F;
cerr << "F= "; cin >> F;

calc(3.14,[&](double z) -> double { return F*z; } );
}

But it fails, since it cannot convert the lambda-expression to
a double (*)(double).

What is the correct declaration of the function 'calc'.

Many thanks for a hint and pointers to tutorials on that subject.
Sorry, but I couldn't extract that information out of the N2550 document.

Helmut.

--
Helmut Jarausch

Lehrstuhl fuer Numerische Mathematik
RWTH - Aachen University
D 52056 Aachen, Germany

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Daniel Krügler on
On 14 Apr., 20:19, Helmut Jarausch <jarau...(a)igpm.rwth-aachen.de>
wrote:
> how can I declare a function which takes a lambda-expression.
> Naively, I tried
>
> // compile with gcc-4.5 -std=c++0x
>
> #include <iostream>
> using std::cout; using std::cerr; using std::cin; using std::endl;
>
> void calc(double x, double CVT(double)) {
> cout << "\nresult= " << CVT(x) << endl;
>
> }
>
> int main() {
> double F;
> cerr << "F= "; cin >> F;
>
> calc(3.14,[&](double z) -> double { return F*z; } );
> }
>
> But it fails, since it cannot convert the lambda-expression to
> a double (*)(double).
>
> What is the correct declaration of the function 'calc'.
>
> Many thanks for a hint and pointers to tutorials on that subject.
> Sorry, but I couldn't extract that information out of the N2550 document.

The most recent working draft is N3090 (which has
the same content as the recently passed FCD).

Regarding your particular use-case there does not
exist a non-template solution. The current wording
says that any lambda closure with *no* lambda-capture
has a publicly available conversion function to
pointer to function that has the same return type
and parameter types as the lambda closure. In your
example you use a non-empty capture (and you need
that), so you would need to provide a template
function that uses the function call operator
of the closure.

HTH & Greetings from Bremen,

Daniel Kr�gler


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Mathias Gaunard on
On 14 avr, 19:19, Helmut Jarausch <jarau...(a)igpm.rwth-aachen.de>
wrote:
> Hi,
>
> how can I declare a function which takes a lambda-expression.
> Naively, I tried
>
> // compile with gcc-4.5 -std=c++0x
>
> #include <iostream>
> using std::cout; using std::cerr; using std::cin; using std::endl;
>
> void calc(double x, double CVT(double)) {
> cout << "\nresult= " << CVT(x) << endl;
>
> }
> [...]
> What is the correct declaration of the function 'calc'.

template<typename F>
void calc(double x, F&& CVT) {
cout << "\nresult= " << CVT(x) << endl;
}

Alternatively you can use std::function or std::nested_function.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Juan Pedro Bolivar Puente on
On 14/04/10 21:19, Helmut Jarausch wrote:
> Hi,
>
> how can I declare a function which takes a lambda-expression.
> Naively, I tried
>
> [...]
>
> What is the correct declaration of the function 'calc'.
>

Every lambda expression has its own type which is known only by the
compiler. To store the lambda expression in a local variable you can use
'auto' to infer its type, but to pass it to another function you can:

a) Make that function a template so the compiler can instantiate it with
the exact inferred type of the lambda.

This is:

template <typename Func>
void calc (double x, Func cvt);

b) Use std::function for type erasure, this is:

void calc (double x, std::function <double (double)> cvt);

The (a) case is more efficient because the function is instantiated for
the exact type of the lambda and potentially use the stack to store the
closure while (b) would potentially store the closure in the heap and
add a extra level of indirection. On the other hand, (a) has all the
limitations of templated functions: cannot be overriden in sub-classes,
their implementation have to be exposed in header files, etc, while
option (b) does not.

JP

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Hakusa on
On Apr 14, 2:19 pm, Helmut Jarausch <jarau...(a)igpm.rwth-aachen.de>
wrote:
> Hi,
>
> how can I declare a function which takes a lambda-expression.
> Naively, I tried

> void calc(double x, double CVT(double)) {
> cout << "\nresult= " << CVT(x) << endl;
>
> }

> int main() {
> double F;
> cerr << "F= "; cin >> F;
>
> calc(3.14,[&](double z) -> double { return F*z; } );
>
> }
>
> But it fails, since it cannot convert the lambda-expression to
> a double (*)(double).
>
> What is the correct declaration of the function 'calc'.

Making calc work only for lambdas might be difficult, they have no
standard-defined type. But, i don't think you want to make it so calc
will take ONLY lambdas anyway, since the usability of it will be
limited, especially to people NOT using -std=c++0x when they compile.

template< typename F >
void calc( double x, F f )
{
cout << "\nresult= " << f(x) << endl;
}

Here, the argument f can be a function pointer, a function object, or
a lambda. As long as type F fulfills to requirement of having
operator()(double), this will work. You can also use
std::tr1::function which has a typedef for result_type.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]