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
c++ - Can the 'type' of a lambda expression be expressed? - Stack Overflow
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;
}
No, you cannot put it into decltype because
A lambda-expression shall not appear in an unevaluated operand
You can do the following though
auto n = { return l > r; };
std::set<int, decltype(n)> s(n);
But that is really ugly. Note that each lambda expression creates a new unique type. If afterwards you do the following somewhere else, t has a different type than s
auto m = { return l > r; };
std::set<int, decltype(m)> t(m);
You can use std::function here, but note that this will incur a tiny bit of runtime cost because it needs an indirect call to the lambda function object call operator. It's probably negligible here, but may be significant if you want to pass function objects this way to std::sort for example.
std::set<int, function<bool(int, int)>> s( { return l > r; });
As always, first code then profile :)
Since C++ 20, lambdas without captures are default constructible, so one can simply pass decltype of the lambda inline as the second template parameter to std::set.
std::set<int, decltype({return l > r;})> s2;
Of course, in this specific case of reversing the natural order, std::greater is more appropriate.
std::set<int, std::greater<>> s2;