【问题标题】:Why does `std::set::extract` not support heterogeneous lookup as `std::set::find`?为什么`std::set::extract`不支持异构查找作为`std::set::find`?
【发布时间】:2021-10-04 00:52:29
【问题描述】:
#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 不支持异构查找 std::set::find

【问题讨论】:

  • 这不是您问题的答案,但您可以通过使用 coll.extract(coll.find("abc"sv)); 绕过此限制而不会造成太多(如果有的话)性能损失
  • @Kaznov - 差不多。 IIUC 您传递给extract 的迭代器必须有效。因此,需要在尝试提取之前检查结束迭代器。尽管如此,这还是有一个非常合理的解决方法的好处。
  • 建议为P2077R2

标签: c++ stl c++17 c++14 standards


【解决方案1】:

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&amp;&amp; 可以隐式转换为 iteratorconst_iterator,则不会选择此重载。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-06
    相关资源
    最近更新 更多