29

I'm trying to implement a map with a lambda function in C++11 as such

std::map<int, int, [](const int&a, const int& b) { return a < b; }> test;

but that fails with

error: type/value mismatch at argument 3 in template parameter list for ‘template<class _Key, class _Tp, class _Compare, class _Alloc> class std::map’

error: expected a type, got ‘{}’

error: invalid type in declaration before ‘;’ token

Any advice?

Community
  • 1
  • 1
ygr
  • 373
  • 1
  • 3
  • 6
  • 2
    You've provided a lambda, i.e. an object; the template parameter must be a _type_, not an instance of a type. – ildjarn Jan 05 '12 at 02:56
  • Refer to [C++ priority_queue with lambda comparator error](http://stackoverflow.com/questions/5807735/c-priority-queue-with-lambda-comparator-error) and [Can the 'type' of a lambda expression be expressed?](http://stackoverflow.com/questions/3867276/can-the-type-of-a-lambda-expression-be-expressed). – Jesse Good Jan 05 '12 at 03:03

1 Answers1

42

You need to pass the type of the lambda as a template argument, not the lambda itself. What you want is this:

auto mycomp = [](const int&a, const int& b) { return a < b; };
std::map<int, int, decltype(mycomp)> test(mycomp);

Although in fact, since your lambda has no captures, it can actually be stored in a function pointer, so alternatively, you could do this:

std::map<int, int, bool(*)(const int&,const int&)>
    test([](const int&a, const int& b) { return a < b; });

Though I find the first much more readable. Although using the function pointer type is more versatile. i.e. It can accept any function pointer or non-capturing lambda that matches that signature. But if you change your lambda to be capturing, it will not work. For a more versatile version, you could use std::function, i.e:

std::map<int, int, std::function<bool(const int&, const int&)>>

That will work with any function, lambda(capturing or not) or function object, as long as the signature matches.

Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
  • Note that if 2 maps were declared they would have 2 different types and be incompatible. – Jesse Good Jan 05 '12 at 03:16
  • @Jesse: That would be one argument for using a function pointer type instead of decltype on the lambda, like I did in my second example. But better(for compatibility, not efficiency) would be to use an `std::function`, then it would be compatible even with lambdas that capture and other function objects. – Benjamin Lindley Jan 05 '12 at 03:25
  • Note that the `std::function<>` approach will incur more overhead than the function pointer approach due to type-erasure. – ildjarn Jan 05 '12 at 05:32
  • 2
    … and the `bool (*)(…)` raw function pointer version may incur indirect function call overhead over the `decltype` version, which is likely to be the fastest. – Potatoswatter Jan 05 '12 at 12:07