【问题标题】:Why does std::map not always allow a compatible type as its key type?为什么 std::map 并不总是允许兼容类型作为其键类型?
【发布时间】:2016-12-28 04:09:19
【问题描述】:
#include <map>
#include <string>
#include <string_view>

using namespace std;

int main()
{
    string_view key = "hello";      
    map<string, int, less<>> coll;
    coll.find(key); // ok
    coll[key] = 0;  // !!! error ???
}

密钥类型为std::string,兼容类型为std::string_view。从 C++14 开始,std::map::find 允许使用兼容的密钥;所以coll.find(key); 没问题。

但是,为什么不coll[key] = 0;也可以?

【问题讨论】:

  • 因为 [] 在 14 中没有得到更多的重载,不像 find...?
  • operator[] 在找不到时也会插入
  • @deviantfan,为什么不超载 []?
  • @Danh 当参数可转换为 key_type 时,这可能不是问题。
  • @Orient 这个问题写得不好,他想问的是为什么关联没有异构比较

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


【解决方案1】:

coll.find(key) 只要求key 与实际密钥类型可比std::string_viewstd::string 可比。但是,为了能够将key 插入collkey 需要可转换std::string,但事实并非如此(无论如何都是隐式的)。

【讨论】:

  • 我相信 OP 是在问为什么 find 被重载以推断类型而 operator[] 没有以相同的方式扩展,而不是为了解释错误
【解决方案2】:

N3465 中描述了背后的基本原理。

从概念上讲,该扩展包括将基于严格弱排序的原始公式替换为依赖于序列分区概念的公式,正如 David Abrahams 首次提出的那样。不幸的是,对于关联容器的查找操作并没有进行这种扩展过程,关联容器仍然是按照严格的弱排序来制定的,因此不允许异构 比较。

以N3465为例,稍作修改:

struct name_entry
{
    std::string family_name;
    std::string given_name;
};
auto as_tuple(const name_entry& e)
{
     return std::tie(e.family_name, e.given_name);
}
bool operator<(const name_entry& x, const name_entry& y)
{
    return as_tuple(x) < as_tuple(y);
}
bool operator<(const name_entry& x, const std::string& y) 
{
    return x.family_name<y;
}
bool operator<(const std::string& x, const name_entry& y) 
{
    return x<y.family_name;
}
int main()
{
    std::set<name_entry, std::less<>> names;
} 

异构比较的发明是为了与找到满足部分比较的包含对象进行决斗,例如找到某人具有给定的姓氏。

另一方面,operator[]会构造一个value_type,如果没有找到key,这个操作需要应用严格的弱排序,因此不能用于异构比较

【讨论】:

  • 我猜那些operator() 应该是operator&lt;?无论如何,理智的operator&lt; 实现而不是手动进行比较:return std::tie(x.family_name, x.given_name) &lt; std::tie(y.family_name, y.given_name);
  • @ildjarn 是的,我从那篇论文中复制而来,没有太大变化。现在将编辑。关于std::tie,我知道这样更好,就像我说的,我从那篇论文中复制的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-17
相关资源
最近更新 更多