This is shown in the debugging window.
I wish to replace the auto
keyword with the original data type. I have tried the following but it fails:
HttpResponse say_hello = [](const HttpRequest& request) -> HttpResponse {...}
Could someone tell me why it is wrong? What is the correct solution? Thank you so much!!!
CodePudding user response:
I think it's important to know the 3 following methods when working with lambdas. The three firsts do essentially the same thing: storing the lambda for future use. The other seems to be what you expect from your code: you directly call the lambda and get the result, so the return type is the type returned by the lambda.
#include <iostream>
#include <functional>
int main()
{
// Auto store the lambda
auto auto_keyword = [](int a) -> int
{ return a; };
std::cout << auto_keyword(42) << std::endl;
// std::function store the lambda
std::function<int(int)> std_function = [](int a) -> int
{ return a; };
std::cout << std_function(42) << std::endl;
// raw function pointer
int (*raw_fptr)(int) = [](int a) -> int
{ return a; };
std::cout << raw_fptr(42) << std::endl;
// direct call to the lambda. (what you expect from your question)
std::cout << ([](int a) -> int{ return a; })(42) << std::endl;
return 0;
}
A lot of things happen here, and i suggest you to read at least this page form the reference for a better understanding.
CodePudding user response:
Normally, a lambda expression is a anonymous function object and it don't have named type. However, sometimes we can use type erasing. If a lambda expression don't capture any argument like your example, it can convert to function pointer implicitly. If a lambda expression capture some arguments, it can convert to std::function.
CodePudding user response:
According to cppreference, (emphasize mine)
The lambda expression is a prvalue expression of unique unnamed non-union non-aggregate class type, known as closure type
As the type of a lambda expression is an unnamed type you cannot use it in a declaration. That is the reason why auto
is the common usage for a lambda.
If you want to be more explicit for the arguments and return type, you can store the lambda in a std::function
variable:
std::function<HttpResponse(const HttpRequest&)> say_hello = ...
But std::function
is still not really the type of the lambda (which is unnamed...), it is just the type of a variable which is able to hold that lambda, as it could old the address of a plain function.
For further reference, draft n4860 for C 20 says at 7.5.5.1 Closure types [expr.prim.lambda.closure] §1
The type of a lambda-expression (which is also the type of the closure object) is a unique, unnamed non-union class type, called the closure type ...
CodePudding user response:
From C standard
[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.
In short each instance of a lambda is its own unique unnamed type.
[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.
Since lambda has function call operator defined you can assign it to std::function
[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.
If the lambda does not capture anything it can be converted to a function pointer.