Is there a reason why I cannot pass a comparison functor to a map
as a constructor argument:
map<int, string, greater<int>> foo;
//map<int, string> foo(greater<int>()); Doesn't work
Or why I cannot pass a lambda without providing my own comparison type:
map<int, string, function<bool(const int&, const int&)>> bar([](const int& lhs, const int& rhs){ return lhs > rhs; });
//map<int, string> bar([](const int& lhs, const int& rhs){ return lhs > rhs; }); Doesn't work
I'd like to just be able to declare map<int, string>
and construct it with a comparator. Why can't I?
This question stems from a misconception. To clear that up:
Functors are objects not functions
Trying to assign a function pointer or a lambda to an object doesn't make any sense. So this cannot be done: The way to define a map<int, string> bar([](const int& lhs, const int& rhs){ return lhs > rhs; });
map
which takes a function pointer or lambda is to use the template arguments from the question: map<int, string, function<bool(const int&, const int&)>>
Halfway between the two ill-conceived options in the question is another misconception: Doesn't work because the comparator template argument is the type of a member of map<int, string, [](const int& lhs, const int& rhs){ return lhs > rhs; }>
map
, not the intialization value. So a map
using a function pointer or lambda comparator must always have that value passed to the map
constructor: map<int, string, function<bool(const int&, const int&)>> bar([](const int& lhs, const int& rhs){ return lhs > rhs; })
Otherwise function<bool(const int&, const int&)>()
would be used for comparisons in the map
.
This is probably already clear by now, but since functors are objects you cannot pass an unrelated object is the construction value of a completely different type of object. Calling is like calling map<int, string> foo(greater<int>())
. The only acceptable compatator constructor argument to a less<int> foo = greater<int>
map
whose comparator template argument is a functor is something that can be converted into an object of the functor type in the template argument: map<int, string, greater<int>> foo(greater<int>{})
This is obviously unnecessary, because if no argument was provided and the greater<int>
was default constructed the same member initialization of the map
would result, so map<int, string, greater<int>>
is sufficent.