The following code fails to build on recent compilers (g++-5.3, clang++-3.7).
#include <map> #include <functional> #include <experimental/string_view> void f() { using namespace std; using namespace std::experimental; map<string, int> m; string s = "foo"; string_view sv(s); m.find(sv); }
Error returned by clang :
error: no matching member function for call to 'find' m.find(sv); ~~^~~~
But shouldn't find
be able to use comparable types ? Cppreference mentions the following overload :
template< class K > iterator find( const K& x );
The same error happens with boost::string_ref
.
std::map::find() find() is used to search for the key-value pair and accepts the “key” in its argument to find it. This function returns the pointer to the element if the element is found, else it returns the pointer pointing to the last position of map i.e “map.end()” . // C++ code to demonstrate the working of find()
That way the map owns the string, and the string view points into that copy only. It also prevents accidentally making a copy of the map and other things that might be equally dangerous. EDIT: it occurs to me that changing the string after it's in the map is another danger you need to watch out for.
But the string view is pointing to the original, not the copy. As soon as the original goes out of scope (when b and c go out of scope, in this case), the string view is no longer valid. And that's just dangerous, in my mind.
If all keys are smaller than the key to be found, it points to “map.end ()” Yet another function to search in map, it returns the range containing the searched key. As map contains unique elements, range returned contains at most 1 element.
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
, andequal_range
shall not participate in overload resolution unless the qualified-idCompare::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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With