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! ]
|
|
0
|
|
|
|
Reply
|
jarausch2 (106)
|
4/14/2010 12:19:03 PM |
|
On 14 Apr., 20:19, Helmut Jarausch <jarau...@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! ]
|
|
0
|
|
|
|
Reply
|
ISO
|
4/14/2010 4:58:10 PM
|
|
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! ]
|
|
0
|
|
|
|
Reply
|
Juan
|
4/14/2010 4:59:07 PM
|
|
On 14 avr, 19:19, Helmut Jarausch <jarau...@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! ]
|
|
0
|
|
|
|
Reply
|
Mathias
|
4/14/2010 4:59:25 PM
|
|
On Apr 14, 2:19 pm, Helmut Jarausch <jarau...@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! ]
|
|
0
|
|
|
|
Reply
|
Hakusa
|
4/14/2010 5:00:35 PM
|
|
On 14 Apr., 20:19, Helmut Jarausch 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).
The C++ standard will allow conversions to function pointers but not
in cases like these. Remember that the lambda syntax does two things:
It defines a new nameless type and creates an object of this type. In
its operator() member function you access something called F. You
could think of F as a reference member of that class. With this im
mind it should be obvious why there cannot be a conversion to a
function pointer. Your pointer CVT is a pointer to a free function
which doesn't have any kind of data or reference to data (like F)
attached to it.
> What is the correct declaration of the function 'calc'.
You have basically two options. 1.:
template<class Fun>
void calc(double x, Fun fun)
{
cout << "\nresult= " << fun(x) << endl;
}
2.:
#include <function>
void calc(double x, std::function<double(double)> fun)
{
cout << "\nresult= " << fun(x) << endl;
}
Cheers,
SG
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
SG
|
4/14/2010 5:34:05 PM
|
|
> how can I declare a function which takes a lambda-expression.
> Naively, I tried
I think you have two options:
1) Use template argument T
2) Use std::function argument
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Thiago
|
4/14/2010 5:37:07 PM
|
|
Hi,
::But it fails, since it cannot convert the lambda-expression to
::a double (*)(double).
I suspect that you received the following warning (or similar):
lambdaold.cpp:31:53: error: cannot convert ‘main()::<lambda(double)>’ to ‘double (*)(double)’ for argument ‘2’ to ‘void calc(double, double (*)(double))’
::What is the correct declaration of the function 'calc'.
I think the warning is related to the fact, that the lambda function uses variables local to the function main (). The following compiles here (gcc version 4.5.0 20100404 (experimental) [trunk revision 157958] (Debian 4.5-20100404-1)) without a warning:
#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 a = 10;
int main() {
calc (2.71, [&](double z) -> double { return a*z; });
}
Whereas it failes with the upper error message using
int main() {
int a = 10;
calc (2.71, [&](double z) -> double { return a*z; });
}
I don't know if the error your source reproduces should be considered as a bug, what does the c++0x say about lambda expressions which use local variables?
Greetings, Magnus
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Magnus
|
4/14/2010 5:41:38 PM
|
|
On 15 Apr., 01:41, Magnus M�ller <mamue...@informatik.hu-berlin.de>
wrote:
> Hi,
>
> ::But it fails, since it cannot convert the lambda-expression to
> ::a double (*)(double).
>
> I suspect that you received the following warning (or similar):
> lambdaold.cpp:31:53: error: cannot convert �main()::<lambda(double)>� to �double (*)(double)� for argument �2� to �void calc(double, double (*)(double))�
>
Well, this looks like a funny description of a "warning" ;-)
> ::What is the correct declaration of the function 'calc'.
>
> I think the warning is related to the fact, that the lambda function uses variables local to the function main (). The following compiles here (gcc version 4.5.0 20100404 (experimental) [trunk revision 157958] (Debian 4.5-20100404-1)) without a warning:
>
> #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 a = 10;
> int main() {
> calc (2.71, [&](double z) -> double { return a*z; });
> }
If this is well-formed, the compiler provides an
extension. Per current working draft there should
be no conversion function for lambda closures with
a lambda-capture. In your example exists a lambda-
capture, even though there is no captured variable.
But the term lambda-capture is defined per grammar
and the code uses this grammar, therefore this
code should be ill-formed.
> Whereas it failes with the upper error message using
>
> int main() {
> int a = 10;
> calc (2.71, [&](double z) -> double { return a*z; });
>
> }
>
> I don't know if the error your source reproduces should be considered as a bug, what does the c++0x say about lambda expressions which use local variables?
>
The current working draft refers to the existence
or absence of lambda-capture. This is the "[&]"
in above example and can take different forms.
If no lambda-capture exists, there is the guarantee
that no local variables are "captured". This is
necessary to allow for a conversion function to
a pointer to a function, because this pointer
must point to some function that can be defined
without state.
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! ]
|
|
0
|
|
|
|
Reply
|
ISO
|
4/15/2010 12:53:17 AM
|
|
|
8 Replies
215 Views
(page loaded in 0.134 seconds)
Similiar Articles: Lambda and cast to pointer to void - comp.lang.c++// 2) is it (then) legal to cast the pointer to the lambda to a pointer to void (reading 5.1.2/3 tells me that the type of a lambda expression if of "class type", so I ... Assigning value to symbolic expressions in vector - comp.soft-sys ...Defining Temporary Structures Defining Structure Types with Expressions ... ... Lambda Expression Syntax The following example uses the generate function and a ... Magic square : Help with my homework - comp.lang.prolog-----=mesnews_0_1116091355 Content-Type: text/plain; charset="iso-8859-15" Content ... For long, people said that lambda expressions need special syntax support. storing iteration results when using for loop. - comp.soft-sys ...If I type Tope at the command window, I can results for all 4 iterattions, but ... Using the iteration variable in a lambda expression may have unexpected results. Avoiding problems with short-circuit primitive operator&& versus ...It heavily templated code, it > can be almost impossible to track every expression's type ... Boost.Bind, Boost.Lambda, and Boost.Phoenix all overload that operator, and ... Create Loops and variables dynamically - comp.soft-sys.sas ...data data; input postcode $ date :DATE. value units weight height type price; y =3D rannor(1234)*4 + 10; format date date9.; datalines; NW67NA 01MAY2008 ... fittype with function handle / anonymous function - comp.soft-sys ...... supports specifying a function handle as the expression to ... comp.soft-sys.matlab... supports elements of lambda ... fittype - Fit type for curve and surface fitting ... Could anyone give me the spice-mode.el - comp.emacsHi, All I am new to *NIX and I am thinking of writing spice code under Emacs. However, I have no idea of Emacs Lisp. Hence, I could not write a packa... How to get envelope from AM signal without phase shift - comp.dsp ...In the meantime I would like to know if there are solutions for this type of problem. ... of the observation line, and find that >the apparent wavelength equals > >lambda ... Lambda Expressions (C# Programming Guide)A lambda expression is an anonymous function that can contain expressions and statements, and can be used to create delegates or expression tree types. Lambda ExpressionsA lambda expression is a function without a name that calculates and returns a single value. Lambda expressions can be used wherever a delegate type is valid. 7/13/2012 10:37:50 AM
|