首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >std::string是否应该专门化std::less支持异构查找?

std::string是否应该专门化std::less支持异构查找?
EN

Stack Overflow用户
提问于 2022-06-02 12:08:39
回答 1查看 136关注 0票数 1

能够在具有char*的容器中查找find而不需要创建临时字符串对象,这是一个好东西。见:避免std::map::find()的关键构造https://www.cppstories.com/2021/heterogeneous-access-cpp20/还有..。

有理由为什么C++不能为用作键类型的任何类型T启用此功能。

因此,在C++20/23中,我们是AFAIKT,剩下:

代码语言:javascript
运行
复制
int main()
{
    {
        // Slow, constructs temporary
        std::map<std_string, int> m;
        auto it = m.find("Olaf");
    }
    {
        // "Fast" does not need to construct temporary
        std::map<std_string, int, std::less<>> m;
        auto it = m.find("Olaf");
    }
}

然而,-我想知道为什么std::string不自动选择-通过提供一个(部分?)专门化的std::less<std::string>std::string (或者更确切地说是std::basic_string<...>)不能这么做是有什么正当理由的吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-08 10:43:35

我认为最主要的原因是没有人提出。没有什么是魔术发生的,它必须有人提出,然后审查和批准。如果提议的步骤没有发生,什么也不会改变。

但是,应该注意的是,使std::less<std::string>透明对于以下类型来说将是一个巨大的改变:

代码语言:javascript
运行
复制
class StupidString
{
  std::string m_str1;
  std::string m_str2;
public:
  // Constructors etc. ...

  operator std::string() const { return m_str1; }

  std::strong_ordering operator<=>(const std::string& s) const
  { return m_str2 <=> s; }
};

如果直接与std::string相比,或者先转换为std::string,然后再进行比较,该类的行为会有所不同。

今天,将该类的一个实例传递给map<string, int>::find(const string&)将隐式转换为std::string,因此使用m_str1。但是如果std::less<std::string>是透明的,它将使用m_str2进行比较。这将改变行为。

可以说,这门课是愚蠢的,理应停课。自从添加了<=>之后,语言就更不宽容与这种奇怪行为进行不一致的比较。但是,打破的变化总是需要仔细考虑,即使代码,将打破乍一看看起来很愚蠢。

可以使std::less<std::string>能够直接与const char*std::string_view进行比较,而不需要转换(对于operator<来说已经是如此)。

代码语言:javascript
运行
复制
template<>
struct less<string>
{
  bool operator()(const string&, const string&) const noexcept;
  // Not in the standard today:
  bool operator()(const string&, string_view) const noexcept;
  bool operator()(const string&, const char*) const noexcept;
  bool operator()(string_view, const string&) const noexcept;
  bool operator()(const char*, const string&) const noexcept;
};

但这也可能是一个巨大的变化。可转换为std::stringconst char* (或std::stringstd::string_view)的类型现在将无法传递给std::less<std::string>,因为它将变得不明确。这是可以解决的。

代码语言:javascript
运行
复制
template<typename T>
concept string_view_or_char_ptr
   = same_as<string_view> || same_as<T, const char*> || same_as<T, char*>;

template<>
struct less<string>
{
  bool operator()(const string&, const string&) const noexcept;
  // Not in the standard today:
  template<string_view_or_char_ptr T>
  bool operator()(const string&, T) const noexcept;
  template<string_view_or_char_ptr T>
  bool operator()(T, const string&) const noexcept;
};

但这根本帮不上忙。因为这种专门化没有定义is_transparent成员(因为它不完全透明,因为它只接受三种类型,而不是任何类似于std::string的类型),所以关联容器不会定义接受任意键的附加函数模板。因此,额外的less<string>::operator()重载不会被使用,并且在执行find("Olaf")时仍然会得到到std::string的转换。

抱歉的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72476043

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档