#include <set>
#include <string>
#include <string_view>
using namespace std::literals;
int main()
{
auto coll = std::set<std::string, std::less<>>{"abc"s, "xyz"s};
coll.find("abc"sv); // ok
coll.extract("abc"sv); // error
}
See online demo
Why does std::set::extract
not support heterogeneous lookup as std::set::find
?
The overloading of std::set::extract()
in C++17 standard is as follows:
node_type extract(const_iterator position); // (1)
node_type extract(const key_type& x); // (2)
Assume that the following overload exist here (it does not exist in C++17 standard):
template<typename K>
node_type extract(const K& x); // (3)
When an iterator
object is passed to extract()
, you would expect it to be implicitly converted to a const_iterator
and (1) would be called, but in fact (3) would be selected.
This can be avoided by adding the following overload (not in the C++17 standard):
node_type extract(iterator position); // (4)
However, even in this case, if you pass an object that implicitly convertible to iterator
or const_iterator
, (3) will be called.
This may not be what you expect.
P2077R2 proposes to introduce the following overloads with constraints.
template<typename K>
node_type extract(K&& x); // (5)
Constraint: in addition to the presence of Compare::is_transparent, this overload will not be selected if K&&
is implicitly convertible to iterator
or const_iterator
.