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>
Related
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.
The C++ standard defines function objects as:
A function object type is an object type that can be the type of the
postfix-expression in a function call. (link)
First I was thinking that function objects were functors, but then I realized that for a function pointer ptr of type P (not a function, but a function pointer), std::is_object_v<P> is true and can be called with the ptr(Args...) syntax.
I am right that function pointers are considered as function objects by the standard? And if they are not what part of the definition is not satisfied by function pointers?
Yes, they are. The term "object" in C++ standard does not mean "object" in the OOP sense. An int is an object.
Function pointer is what it sounds like: a pointer to function. As itself it's a storage containing a pointer object, which returns a callable of function type.
If you take time and read first chapters of standard, you 'll understand that any variable declaration declares some type of storage that contains objects. Those can be objects of primitive types or classes. Essentially in C++ anything that can be stored is object.
By declaring function pointer you create storage that can store address of that function and operator() can be used
Anther type of callable closure can be created by lambda expression. They are not function objects, each expression creates a unique callable object, but captureless lambdas can be used as one, e.g. to assign it to a function pointer, e.g.
double (*square)(double) = [](double a)->double { return a*a; };
after this you can call it using expression like square(3.6);
For functions and lambda call operator operator() is supplied by language, by defining operator() for a class you create what people often call "functor", which is misnomer because actual functors in mathematics or such languages like Haskell do not store state. Result of lambda expression is a "functor" created by compiler, which stores states of captured objects.
Naming those objects callable might be a little misleading too, because as a concept in C++, a callable object is any object that can be used with INVOKE operation, which include pointers to data members even while no function calls happen.
it leaves only one option, if we can use function call with said object, it's a function object. It can be function, lambda expression, function object, function pointer, member function pointer with specified class instance ( obj.*memberptr or objptr->*memberptr - call of member function is very special) - they are function objects.
The function pointer are function object, but they also have a funny quirk coming from C era:
#include <iostream>
int foo(int a)
{
std::cout << "Hello, " << a << " stars\n";
return a;
}
int (*pr) (int) = foo;
int main()
{
pr(0);
(*pr)(1);
(**pr)(2);
(***pr)(3);
return 0;
}
The postfix expression shall have function type or pointer to function type and function is contextually convertible to a function pointer whenever such conversion is required, so repeating dereference operators bounce type "to and fro", leaving it be a function pointer. Captureless lambda would do too:
// also can write `auto pr2 = ...`
int (*pr2) (int) = [](int a)->int {
std::cout << "Hello, lambda " << a << " stars\n"; return a;
};
// in main()
(**pr2)(2);
Naturally, that code is ill-formed if pr is a generalized "functor"
int b = 2;
auto pr3 = [=]()->int {
std::cout << "Hello, general lambda " << b << std::endl;
return b;
};
pr3();
//(*pr3)(); Ill-formed: not a pointer!
I have read the item31 of "Effective Modern C++" and web page of http://en.cppreference.com/w/cpp/language/lambda and wonder if I can define a lambda by its definite type instead of the wrapped type of std::function or keyword of auto and how can I accomplish that.
for instance, for the type int:
auto x_1 = 5; // type deduction
int x_2 = 5; // defined by definite type
// both x_1, x_2 are int variables of value 5
now, when the problem comes to the lambda:
auto f_1_0 = []()->int{return 5;};
std::function<int(void)> f_1_1 = []()->int{return 5;};
SomeType f_2 = []()->int{return 5;}; // what's the SomeType here?
Each lambda expression has its own unique type.
Here the expressions f_1 and f2 have different types.
auto f_1 = []()->int {return 5; };
auto f_2 = []()->int {return 5; };
Assigning f_2 = f_1 is illegal.
The standard says the types are "unnamed." In practice, the compiler probably makes up a new, hiiden typename for each lambda. Visual C++17 gave them the following names.
classmain::<lambda_7e9d7fb093569d78a8c871761cbb39d7>
classmain::<lambda_8f061a3967cd210147d6a4978ab6e125>
Not very useful information.
The standard says that the type of the lambda is unnamed so the implementation creates a implementation defined name it uses similar to the other unnamed classes, structs enumc etc.
ISO C++: 5.1.2 Lambda expressions [expr.prim.lambda]
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.
The standard also says that the lambda 'behaves like a function' so you it could be used with the std::function template:
[Note: A closure object behaves like a function object (20.9).—end note]
And if you really want to have names for your can use the old-fashioned functors and do all the work the compiler do for you with the lambdas.
in some cases you can use function pointers (using mvcpp, 0x17):
auto usingAuto = []() {
cout << "autoMagick" << endl;
};
void(*pureCpp)() = []() {
cout << "pureCpp" << endl;
};
//pureCpp = usingAuto; //you can even assing function pointers from lambdas
//usingAuto = pureCpp; //error
pureCpp();
usingAuto();
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; }
};
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>