You need to specify a transparent comparator explicitly (like std::less<>
):
std::map<std::string, int, std::less<>> m;
// ~~~~~~~~~~^
std::map<K,V>
defaults its comparator to std::less<K>
(i.e., a non-transparent one), and since ([associative.reqmts]/p13):
The member function templates find
, count
, lower_bound
, upper_bound
, and equal_range
shall not participate in overload resolution unless the qualified-id Compare::is_transparent
is valid and denotes a type (14.8.2).
the template member function find
is not a viable candidate.
Heterogeneous comparison lookup for associative containers was added to c++14. The original proposal risked breaking existing code. For example:
c.find(x);
is semantically equivalent to:
key_type key = x;
c.find(key);
In particular, the conversion between x
and key_type
happens only once, and before the actual call.
Heterogenous lookup replaces this conversion in favour of a comparison between key
and x
. This may lead to a drop in performance in existing code (due to addtional conversion before each comparison) or even break compilation (if the comparison operator is a member function, it will not apply conversion for a left-hand side operand):
#include <set>
#include <functional>
struct A
{
int i;
A(int i) : i(i) {}
};
bool operator<(const A& lhs, const A& rhs)
{
return lhs.i < rhs.i;
}
int main()
{
std::set<A, std::less<>> s{{1}, {2}, {3}, {4}};
s.find(5);
}
DEMO
To resolve this the new behaviour was made opt-in by adding the concept of transparent comparators as described in the linked question.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…