Is it possible to express the "type" of a lambda expression?

When thinking of lambda expressions as “syntactic sugar” for called objects, can an unnamed base type be expressed?

Example:

struct gt { bool operator() (int l, int r) { return l > r; } } ; 

Now [](int l, int r) { return l > r; } [](int l, int r) { return l > r; } is an elegant replacement for the above code (plus the necessary creation of gt callable objects), but is there any way to express gt (the type itself)?

Simple use:

 std::set<int, gt> s1; // A reversed-order std::set // Is there a way to do the same using a lambda? std::set<int, some-magic-here-maybe([](int l, int r) { return l > r; }) > s2; 
+46
c ++ lambda c ++ 11 stl
Oct 05 2018-10-10 at
source share
3 answers

No, you cannot put it in decltype because

Lambda expression must not appear in an unpublished operand

You can do the following though

 auto n = [](int l, int r) { return l > r; }; std::set<int, decltype(n)> s(n); 

But it is really ugly. Note that each lambda expression creates a new unique type. If you subsequently do the following elsewhere, t is of a different type than s

 auto n = [](int l, int r) { return l > r; }; std::set<int, decltype(n)> t(n); 

You can use std::function , but note that this will entail a tiny runtime cost, since this requires an indirect call to the operator to call the lambda function object. This is probably negligible here, but can be significant if you want to pass function objects this way, for example, std::sort .

 std::set<int, function<bool(int, int)>> s([](int l, int r) { return l > r; }); 

As always, first the code and then the profile :)

+50
Oct 05 '10 at 20:11
source share

A direct answer to your question: None.

You will need to use what can be assigned from any type that looks like a functor with a well-defined type. One example is std :: function, as shown in sbi's answer. This, however, is not a type of lambda expression.

+1
Oct 05 '10 at 20:11
source share

You can use the small lambda_wrapper <> class to wrap lambda at low cost. This is much faster than the std :: function, because there is no virtual function call and dynamic memory allocation. Wrapper works by listing the lambda arguments and the return type.

 #include <iostream> #include <functional> #include <set> template <typename T, typename ... Args> struct lambda_wrapper : public lambda_wrapper<decltype(&T::operator())(Args...)> {}; template <typename L> struct lambda_wrapper<L> { private: L lambda; public: lambda_wrapper(const L & obj) : lambda(obj) {} template<typename... Args> typename std::result_of<L(Args...)>::type operator()(Args... a) { return this->lambda.operator()(std::forward<Args>(a)...); } template<typename... Args> typename std::result_of<const L(Args...)>::type operator()(Args... a) const { return this->lambda.operator()(std::forward<Args>(a)...); } }; template <typename T> auto make_lambda_wrapper(T&&t) { return lambda_wrapper<T>(std::forward<T>(t)); } int main(int argc, char ** argv) { auto func = make_lambda_wrapper([](int y, int x) -> bool { return x>y; }); std::set<int, decltype(func)> ss(func); std::cout << func(2, 4) << std::endl; } 
-one
Jul 21 '17 at 20:57
source share



All Articles