I can't pass lambda with reference capture - c++

Following code fails with this error
E0413 no suitable conversion function from "lambda []float (int i)->float" to "float (*)(int i)" exists
int test;
float (*f)(int i) = [&](int i) -> float {return test; };
How do I fix this? I need the Capture clause.

You can only do the above with capture-less lambdas.
See [expr.prim.lambda.closure] (sec 7)
The closure type for a non-generic lambda-expression with no
lambda-capture whose constraints (if any) are satisfied has a
conversion function to pointer to function with C++ language linkage
having the same parameter and return types as the closure type's
function call operator.
Since lambdas are not just ordinary functions and capturing it need to preserve a state,
you can not find any simple or conventional solution to make them assign to function pointers.
To fix, you can use std::function which will do it by type erasure:
#include <functional> // std::function
int test;
std::function<float(int)> f = [&](int i) -> float {return static_cast<float>(test); };

A lambda (with captures) is not the same as a function pointer, and cannot be converted to one.
A capture-less lambda can be converted to a function pointer.
See CPPReference, specifically the bit that begins:
A generic captureless lambda has a user-defined conversion function template with the same invented template parameter list as the function-call operator template.

Related

Why can a C++ function type alias be used to pass a lambda to a function?

Have a look at the code example listed below, I tested it with Compiler explorer (using gcc and clang) and it works and prints out the (expected) output of 200.
What I am trying to figure out: why exactly is this valid C++. Or is it not?
Here, I'm using the using keyword to define an alias (instead of a typedef) for the function type ft, which describes functions that take an int as argument and return an int (ft is a function type, not a function pointer type!). The equivalent typedef syntax is typedef int ft(int);. Since the C++ standard says that for every typedef there is an equivalent form using the using syntax, it is clear that using ft = int(int) is a well-defined way to specify this function type.
Now comes the interesting part: I use the type ft to specify the argument type of another function (print_it), and then call it, passing a lambda function. My question is: where/how does the C++ standard say that this should actually work? I think it is a wonderfully simple way to pass lambdas around. That this works is not clear to me, as a lambda is really a functor, not a function in the strict sense. So I think it is not clear that this lambda matches the type ft and therefore can be passed to print_it (if ft was defined to be std::function<int(int)> it would be clear though).
The code example:
#include <iostream>
using ft = int(int);
void print_it (ft f, int a)
{
std::cout << f(a) << std::endl;
}
int main ()
{
auto my_lambda = [] (int a) -> int { return 2 * a; };
print_it (my_lambda, 100);
return (0);
}
My question is: where/how does the C++ standard say that this should actually work?
This is specified in [expr.prim.lambda.closure]/7, which specifies that a lambda's closure type has a conversion function to a function pointer type matching the lambda's parameter and return types if the lambda is non-generic and doesn't have any capture. Calling through this function pointer basically behaves as if the lambda body was just a normal function to which the pointer points, which is possible because there are no captures which could give the lambda a state that a normal function can't have.
This applies here and you are using the conversion operator to implicitly convert the lambda object to a function pointer when passing it to print_it. This works since the lambda's parameter and return type matches the ft type and a function type used as type of a function parameter is adjusted to a pointer-to-function type instead. (See [dcl.fct]/5 for the last part.)
For generic lambdas there is a conversion function template (see the following standard paragraph). For lambdas with a capture there is no such conversion function and therefore this wouldn't work for them.
This only works because your lambda does not capture. A capture-less lambda can be converted to a C-style function pointer but a captureing lambda cannot.

Why Overload resolution is unable to decide which version of an overloaded function to initialize an std::function object?

I have this example about std::function:
int add(int x, int y, int z) {return x + y + z;}
int add(int a, int b) {return a + b;}
int main()
{
std::function<int(int, int)> fn = add; // error
int(*pfn)(int, int) = add; // OK
fn = pfn; // ok fn is bound to add(int, int)
std::cout << fn(5, 7) << std::endl; // 12
}
Why Overload resolution doesn't resolve which version of add when initializing fn but is able to initialize the function pointer pfn?
Is there a workaround rather than using function pointer to decide which version of an overloaded function as an initializer to an std::function object?
Why Overload resolution doesn't resolve which version of add when initializing fn but is able to initialize the function pointer pfn?
Because overload resolution is performed in the initialization of function pointer (like pfn), based on the type of the function pointer.
In all these contexts, the function selected from the overload set is the function whose type matches the pointer to function, reference to function, or pointer to member function type that is expected by target: the object or reference being initialized, the left-hand side of the assignment, function or operator parameter, the return type of a function, the target type of a cast, or the type of the template parameter, respectively.
On the other hand, such overload resolution doesn't happen when initializing a std::function, which has a constructor template and the template parameter needs to be deduced from the function argument; the compiler can't choose one for the deduction.
As the workaround, you can apply static_cast to specify the overload you want explicitly.
static_cast may also be used to disambiguate function overloads by performing a function-to-pointer conversion to specific type
std::function<int(int, int)> fn = static_cast<int(*)(int, int)>(add);
For the function pointer case, C++ has a special rule that permits a sort of "time travelling" lookup. It can perform overload resolution on a name, based on what you're going to assign/initialise the name to.
This is basically a hack built into the language (rules in [over.over]).
No other part of the language works this way. For example, where newcomers often expect that after writing float x = 1/2 the value of x will be 0.5, we have to explain that the fact you're initialising a float has no relevance to the types or calculation of the expression 1/2.
This hack was not extended to std::function. Presumably that is because adding hacks is bad, and because it is not needed for this case. Why not? Because you can still deploy the hack indirectly with a static_cast on the RHS of your std::function initialisation:
std::function<int(int, int)> fn = static_cast<int(*)(int, int)>(add);
… and there's your workaround.

Assign a lambda to a variable in C++ [duplicate]

I had a perception that, type of a lambda is a function pointer. When I performed following test, I found it to be wrong (demo).
#define LAMBDA [] (int i) -> long { return 0; }
int main ()
{
long (*pFptr)(int) = LAMBDA; // ok
auto pAuto = LAMBDA; // ok
assert(typeid(pFptr) == typeid(pAuto)); // assertion fails !
}
Is above code missing any point? If not then, what is the typeof a lambda expression when deduced with auto keyword ?
The type of a lambda expression is unspecified.
But they are generally mere syntactic sugar for functors. A lambda is translated directly into a functor. Anything inside the [] are turned into constructor parameters and members of the functor object, and the parameters inside () are turned into parameters for the functor's operator().
A lambda which captures no variables (nothing inside the []'s) can be converted into a function pointer (MSVC2010 doesn't support this, if that's your compiler, but this conversion is part of the standard).
But the actual type of the lambda isn't a function pointer. It's some unspecified functor type.
It is a unique unnamed structure that overloads the function call operator. Every instance of a lambda introduces a new type.
In the special case of a non-capturing lambda, the structure in addition has an implicit conversion to a function pointer.
[C++11: 5.1.2/3]: The type of the lambda-expression (which is also the type of the closure object) is a unique, unnamed non-union class type — called the closure type — whose properties are described below. This class type is not an aggregate (8.5.1). The closure type is declared in the smallest block scope, class scope, or namespace scope that contains the corresponding lambda-expression. [..]
The clause goes on to list varying properties of this type. Here are some highlights:
[C++11: 5.1.2/5]: The closure type for a lambda-expression has a public inline function call operator (13.5.4) whose parameters and return type are described by the lambda-expression’s parameter-declaration-clause and trailing-return-type respectively. [..]
[C++11: 5.1.2/6]: The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const conversion function to pointer to function having the same parameter and return types as the closure type’s function call operator. The value returned by this conversion function shall be the address of a function that, when invoked, has the same effect as invoking the closure type’s function call operator.
The consequence of this final passage is that, if you used a conversion, you would be able to assign LAMBDA to pFptr.
#include <iostream>
#include <typeinfo>
#define LAMBDA [] (int i)->long { return 0l; }
int main ()
{
long (*pFptr)(int) = LAMBDA; // ok
auto pAuto = LAMBDA; // ok
std::cout<<typeid( *pAuto ).name() << std::endl;
std::cout<<typeid( *pFptr ).name() << std::endl;
std::cout<<typeid( pAuto ).name() << std::endl;
std::cout<<typeid( pFptr ).name() << std::endl;
}
The function types are indeed same, but the lambda introduces new type (like a functor).
It should also note that lambda is convertible to function pointer. However typeid<> returns a non-trvial object which should differ from lambda to generic function pointer. So the test for typeid<> is not a valid assumption. In general C++11 do not want us to worry about type specification, all that matter if a given type is convertible to a target type.
A practical solution from How can I store a boost::bind object as a class member?, try boost::function<void(int)> or std::function<void(int)>.
To further improve jalf's answer
A lambda which captures no variables (nothing inside the []'s) can be converted into a function pointer
for example:
typedef int (*Foo)(int a);
auto bar = [](int a){
return a;
};
int tmp = 1;
auto bar2 = [tmp](int a){
return a+tmp;
};
Foo foo = bar; // this is ok
Foo foo2 = bar2; // this gives C/C++(413)
This might work:
h1 {
font-size:20px;
}
h2{
font-size:18px;
}
p {
font-size: 16px;
}
exmp{
font-size:16px;
color:#000077;
/*font-style: oblique;*/
font-family: Lucida Console;
}
<h1>If you truly insist in defining a datatype other then auto for your lambda variable then I would recommend the following</h1>
<h2>Step 1: </h2>
<p>Typedef a function pointer</p>
<exmp> typedef void(*FuncPointerType)();</exmp>
<p>Note the empty parentheses, this will need to be the same as the arguments later of your lambda <br> Now create a function pointer as you would normaly do.</p>
<exmp>/void (**MyFunction)() = new FuncPointerType([](){});</exmp>
<p>Note that the you will have to go and manually delete the pointer as it is created on the heap<br>Finally call the function pointer, it can be called one of 2 ways:</p>
<exmp>(*(*MyFunction))();</exmp>
<p>OR</p>
<exmp>(*MyFunction)();</exmp>
<p>Note the importance that it should be returnd for a function pointer pointer to just a function pointer.</p>

Type of lambdas in C++

I am trying to learn lambdas in C++, but stumbled on something I can't quite understand.
Here is code:
#include <iostream>
typedef double Func(double);
double applyFunc(Func f, double x)
{
return f(x);
}
int main()
{
std::cout << applyFunc([](double x) {return x + 1;}, 3) << std::endl;
}
Now this works just fine (prints "4"), i.e. type of the lambda expression used is exactly double (*)(double).
But if I add closure to the lambda expression, like:
int main()
{
int n = 5;
std::cout << applyFunc([n](double x) {return x + n;}, 3) << std::endl;
}
Then I get an error from the compiler:
In function ‘int main()’:
error: cannot convert ‘main()::__lambda0’ to ‘double (*)(double)’ for argument ‘1’ to ‘double applyFunc(double (*)(double), double)’
3) << std::endl;
^
And I don't understand why is that. I mean, from the point of view of applyFunc() it still receives a pointer to a function taking double argument and returning double, and it doesn't know that we used variable 'n' from context, so the type of lambda expression should be the same, as in the first example, right?
I would very appreciate help, thank you in advance!
A lambda is convertable to a function pointer only if it does not have a capture, we can see this by going to the draft standard section 5.1.2 Lambda expressions which says (emphasis mine):
The closure type for a lambda-expression with no lambda-capture has a
public non-virtual non-explicit const conversion function to pointer
to function having the same parameter and return types as the closure
type’s function call operator. The value returned by this conversion
function shall be the address of a function that, when invoked, has
the same effect as invoking the closure type’s function call operator.
This is an alternative solution which does not rely on this conversion:
template <typename Callable>
double applyFunc(Callable f, double x)
{
return f(x);
}
Update
If you are interested in the difference between using std::function and templates then you should read std::function vs template. There are many good answers there and a lot of food for thought.
Each lambda expression returns an object with a distinct type. If the lambda expression does not capture any variables, it can be converted to a a function pointer type of an appropriate signature (i.e., the return type and the arguments need to agree with those of the lambda expression). When there is a variable captured, the entity created can't be represented by a plain function. Instead, the lambda expression yields an object of class type with a function call operator. That is, your second code uses a lambda expression yielding an object of a class which is roughly equivalent to this:
class lambda {
int n;
public:
lambda(int n): n(n) {}
double operator()(double x) const { return x + n; }
};

What is the type of lambda when deduced with "auto" in C++11?

I had a perception that, type of a lambda is a function pointer. When I performed following test, I found it to be wrong (demo).
#define LAMBDA [] (int i) -> long { return 0; }
int main ()
{
long (*pFptr)(int) = LAMBDA; // ok
auto pAuto = LAMBDA; // ok
assert(typeid(pFptr) == typeid(pAuto)); // assertion fails !
}
Is above code missing any point? If not then, what is the typeof a lambda expression when deduced with auto keyword ?
The type of a lambda expression is unspecified.
But they are generally mere syntactic sugar for functors. A lambda is translated directly into a functor. Anything inside the [] are turned into constructor parameters and members of the functor object, and the parameters inside () are turned into parameters for the functor's operator().
A lambda which captures no variables (nothing inside the []'s) can be converted into a function pointer (MSVC2010 doesn't support this, if that's your compiler, but this conversion is part of the standard).
But the actual type of the lambda isn't a function pointer. It's some unspecified functor type.
It is a unique unnamed structure that overloads the function call operator. Every instance of a lambda introduces a new type.
In the special case of a non-capturing lambda, the structure in addition has an implicit conversion to a function pointer.
[C++11: 5.1.2/3]: The type of the lambda-expression (which is also the type of the closure object) is a unique, unnamed non-union class type — called the closure type — whose properties are described below. This class type is not an aggregate (8.5.1). The closure type is declared in the smallest block scope, class scope, or namespace scope that contains the corresponding lambda-expression. [..]
The clause goes on to list varying properties of this type. Here are some highlights:
[C++11: 5.1.2/5]: The closure type for a lambda-expression has a public inline function call operator (13.5.4) whose parameters and return type are described by the lambda-expression’s parameter-declaration-clause and trailing-return-type respectively. [..]
[C++11: 5.1.2/6]: The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const conversion function to pointer to function having the same parameter and return types as the closure type’s function call operator. The value returned by this conversion function shall be the address of a function that, when invoked, has the same effect as invoking the closure type’s function call operator.
The consequence of this final passage is that, if you used a conversion, you would be able to assign LAMBDA to pFptr.
#include <iostream>
#include <typeinfo>
#define LAMBDA [] (int i)->long { return 0l; }
int main ()
{
long (*pFptr)(int) = LAMBDA; // ok
auto pAuto = LAMBDA; // ok
std::cout<<typeid( *pAuto ).name() << std::endl;
std::cout<<typeid( *pFptr ).name() << std::endl;
std::cout<<typeid( pAuto ).name() << std::endl;
std::cout<<typeid( pFptr ).name() << std::endl;
}
The function types are indeed same, but the lambda introduces new type (like a functor).
It should also note that lambda is convertible to function pointer. However typeid<> returns a non-trvial object which should differ from lambda to generic function pointer. So the test for typeid<> is not a valid assumption. In general C++11 do not want us to worry about type specification, all that matter if a given type is convertible to a target type.
A practical solution from How can I store a boost::bind object as a class member?, try boost::function<void(int)> or std::function<void(int)>.
To further improve jalf's answer
A lambda which captures no variables (nothing inside the []'s) can be converted into a function pointer
for example:
typedef int (*Foo)(int a);
auto bar = [](int a){
return a;
};
int tmp = 1;
auto bar2 = [tmp](int a){
return a+tmp;
};
Foo foo = bar; // this is ok
Foo foo2 = bar2; // this gives C/C++(413)
This might work:
h1 {
font-size:20px;
}
h2{
font-size:18px;
}
p {
font-size: 16px;
}
exmp{
font-size:16px;
color:#000077;
/*font-style: oblique;*/
font-family: Lucida Console;
}
<h1>If you truly insist in defining a datatype other then auto for your lambda variable then I would recommend the following</h1>
<h2>Step 1: </h2>
<p>Typedef a function pointer</p>
<exmp> typedef void(*FuncPointerType)();</exmp>
<p>Note the empty parentheses, this will need to be the same as the arguments later of your lambda <br> Now create a function pointer as you would normaly do.</p>
<exmp>/void (**MyFunction)() = new FuncPointerType([](){});</exmp>
<p>Note that the you will have to go and manually delete the pointer as it is created on the heap<br>Finally call the function pointer, it can be called one of 2 ways:</p>
<exmp>(*(*MyFunction))();</exmp>
<p>OR</p>
<exmp>(*MyFunction)();</exmp>
<p>Note the importance that it should be returnd for a function pointer pointer to just a function pointer.</p>