views:

125

answers:

2

Thinking of lambda expressions as 'syntactic sugar' for callable objects, can the unnamed underlying type be expressed?

An example:

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

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

A simple usage:

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;
+1  A: 

Direct answer to your question: No.

You'll need to use something that is assignable from any type resembling a functor that has a well defined type. One example is std::function as shown in sbi's answer. That isn't, however, the type of the lambda expression.

Noah Roberts
+10  A: 

Nope, 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 = [](int l, int r) { return l > r; };
std::set<int, decltype(n)> s(n);

But really, that's kinda 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 n = [](int l, int r) { return l > r; };
std::set<int, decltype(n)> t(n);

You can use std::function here, but note that this will incure 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([](int l, int r) { return l > r; });

As always, first code then profile :)

Johannes Schaub - litb
I thought of using `auto` and `declytype` in combination that way when I read the question. *chuckle* Using that combination to extract the type of an expression that isn't really meant to have a visible type is kind of amusing.
Omnifarious