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.
Answer from Stack Overflow is garbage on Stack OverflowThe 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.
Why does C not have lambdas/anonymous function expressions?
what's the type of a lambda expression ? - C++ Forum
c++ - what is the type signature of a c++11/1y lambda function? - Stack Overflow
simple lambda like functions in C
It would not seem to hard to implement to allow a programmer to use a construct similar to:
int (*add)(int, int) = (int(int x, int y)){return x+y;};
This would simplify code that requires callback functions such as qsort or bsearch or various UI libraries that use callbacks to define, for example, a buttons behavior when pressed. Is there any specific reason they elected not to support this, and require us to define named static functions instead?
You are correct the types of C++11 lambdas are anonymous and instance-unique.
the std::function type can store references to any kind of lambda I have come across, but there is said to be a performance hit.
Try
std::function<int (int, int)> f = -> int {
return x + y;
};
note the -> int can be omitted in non ambiguous scenarios such as this.
C++14 lets us write
std::function<int (int, int)> f = {
return x + y;
};
which is handy for long type names.
As noted by @Jonathan Wakely, this approach captures a specific instantiation using std::function with fixed template arguments. In C++14, template variables can be specified. Additionally, also per C++14, lambda parameters can have can have their types inferred via auto, allowing for the following:
template<class T>
std::function<T (T, T)> g = -> auto {
return x + y;
};
Currently, VC++, and GCC do not seem to support templates on variable declarations at function level, but allow them on member, namespace, and global declarations. I am unsure whether or not this restriction emanates from the spec.
Note: I do not use clang.
According to Can the 'type' of a lambda expression be expressed?, there is actually a simple way in current c++ (without needing c++1y) to figure out the return_type and parameter types of a lambda. Adapting this, it is not difficult to assemble a std::function typed signature type (called f_type below) for each lambda.
I. With this abstract type, it is actually possible to have an alternative way to auto for expressing the type signature of a lambda, namely function_traits<..>::f_type below. Note: the f_type is not the real type of a lambda, but rather a summary of a lambda's type signature in functional terms. It is however, probably more useful than the real type of a lambda because every single lambda is its own type.
As shown in the code below, just like one can use vector<int>::iterator_type i = v.begin(), one can also do function_traits<lambda>::f_type f = lambda, which is an alternative to the mysterious auto. Of course, this similarity is only formal. The code below involves converting the lambda to a std::function with the cost of type erasure on construction of std::function object and a small cost for making indirect call through the std::function object. But these implementation issues for using std::function aside (which I don't believe are fundamental and should stand forever), it is possible, after all, to explicitly express the (abstract) type signature of any given lambda.
II. It is also possible to write a make_function wrapper (pretty much like std::make_pair and std::make_tuple) to automatically convert a lambda f ( and other callables like function pointers/functors) to std::function, with the same type-deduction capabilities.
Test code is below:
#include <cstdlib>
#include <tuple>
#include <functional>
#include <iostream>
using namespace std;
// For generic types that are functors, delegate to its 'operator()'
template <typename T>
struct function_traits
: public function_traits<decltype(&T::operator())>
{};
// for pointers to member function
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const> {
//enum { arity = sizeof...(Args) };
typedef function<ReturnType (Args...)> f_type;
};
// for pointers to member function
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) > {
typedef function<ReturnType (Args...)> f_type;
};
// for function pointers
template <typename ReturnType, typename... Args>
struct function_traits<ReturnType (*)(Args...)> {
typedef function<ReturnType (Args...)> f_type;
};
template <typename L>
typename function_traits<L>::f_type make_function(L l){
return (typename function_traits<L>::f_type)(l);
}
long times10(int i) { return long(i*10); }
struct X {
double operator () (float f, double d) { return d*f; }
};
// test code
int main()
{
auto lambda = { return long(i*10); };
typedef function_traits<decltype(lambda)> traits;
traits::f_type ff = lambda;
cout << make_function( { return long(i*10); })(2) << ", " << make_function(times10)(2) << ", " << ff(2) << endl;
cout << make_function(X{})(2,3.0) << endl;
return 0;
}