为什么 `std::set::extract` 不像 `std::set::find` 那样支持异构查找?

Why does `std::set::extract` not support heterogeneous lookup as `std::set::find`?

#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
}

online demo

为什么std::set::extract not support heterogeneous lookup as std::set::find

C++17标准中std::set::extract()的重载如下:

node_type extract(const_iterator position);  // (1)
node_type extract(const key_type& x);        // (2)

假设这里存在如下重载(在C++17标准中不存在):

template<typename K>
node_type extract(const K& x);               // (3)

iterator 对象被传递给 extract() 时,您会期望它被隐式转换为 const_iterator 并且 (1) 将被调用,但实际上 (3 ) 将被选中。

这可以通过添加以下重载(不在 C++17 标准中)来避免:

node_type extract(iterator position);        // (4)

但是,即使在这种情况下,如果您传递一个可隐式转换为 iteratorconst_iterator 的对象,(3) 也会被调用。 这可能不是你所期望的。


P2077R2 建议引入以下带约束的重载。

template<typename K>
node_type extract(K&& x);                    // (5)

约束:除了 Compare::is_transparent 的存在之外,如果 K&& 可隐式转换为 iteratorconst_iterator,则不会选择此重载。