为什么 std::hash<const std::string> 不专攻 std?
Why isn't std::hash<const std::string> specialized in std?
为什么 std::hash<const std::string>
不专攻性病?
它会导致像
这样的编译错误
std::unordered_map<const std::string, int> m;
m.insert(std::make_pair("Foo", 1)); //error
m["Bar"] = 2; // also error
有什么原因吗?
Why isn't std::hash<const std::string>
specialized in std?
事实上,std 没有特化任何 std::hash<const T>
。原因可能是不需要。对于任何 std::hash<T>
,它唯一的功能是一个 operator()
,它将 const T&
作为参数。因此,即使 std::hash<const Foo>
被专门化,它也将与 std::hash<Foo>
.
完全相同
然后回到你遇到麻烦的代码,它真的应该是:
std::unordered_map<std::string, int> m;
这里,虽然key_type
是std::string
,但是key的实际类型其实是const std::string
,可以用decltype(m)::value_type::first_type
.[=33=访问]
更新:
When you think of concept of hash, the key should not be changed, so specilaization of std::hash looks more appropriate than std::hash. Don't you agree ?
当然哈希函数不会也不应该更改密钥,但同时,它可能不应该复制,所以为什么不选择 std::hash<const T&>
?
需要注意的一件事是,被特化的类型并不总是等于参数类型。模板参数更多的是关于散列函数与什么类型相关,而不是传递给调用运算符的是什么。类似地,numeric_limits<T>
期望一个非 cv 限定的数字类型作为类型 T
。这并不意味着 const int
和 const double
没有各自的限制。除非您期望在 hash<T>
和 hash<const T>
上有不同的行为,否则为什么要将它们特化两次?
还有一件事要注意,std::hash
实际上更像是一个与 unordered_XXX
系列捆绑在一起的实用程序 class,主要用作无序的哈希函数family 默认情况下,或用于为要提供给无序系列的自定义类型定义自定义哈希函数。
为什么 std::hash<const std::string>
不专攻性病?
它会导致像
这样的编译错误std::unordered_map<const std::string, int> m;
m.insert(std::make_pair("Foo", 1)); //error
m["Bar"] = 2; // also error
有什么原因吗?
Why isn't
std::hash<const std::string>
specialized in std?
事实上,std 没有特化任何 std::hash<const T>
。原因可能是不需要。对于任何 std::hash<T>
,它唯一的功能是一个 operator()
,它将 const T&
作为参数。因此,即使 std::hash<const Foo>
被专门化,它也将与 std::hash<Foo>
.
然后回到你遇到麻烦的代码,它真的应该是:
std::unordered_map<std::string, int> m;
这里,虽然key_type
是std::string
,但是key的实际类型其实是const std::string
,可以用decltype(m)::value_type::first_type
.[=33=访问]
更新:
When you think of concept of hash, the key should not be changed, so specilaization of std::hash looks more appropriate than std::hash. Don't you agree ?
当然哈希函数不会也不应该更改密钥,但同时,它可能不应该复制,所以为什么不选择 std::hash<const T&>
?
需要注意的一件事是,被特化的类型并不总是等于参数类型。模板参数更多的是关于散列函数与什么类型相关,而不是传递给调用运算符的是什么。类似地,numeric_limits<T>
期望一个非 cv 限定的数字类型作为类型 T
。这并不意味着 const int
和 const double
没有各自的限制。除非您期望在 hash<T>
和 hash<const T>
上有不同的行为,否则为什么要将它们特化两次?
还有一件事要注意,std::hash
实际上更像是一个与 unordered_XXX
系列捆绑在一起的实用程序 class,主要用作无序的哈希函数family 默认情况下,或用于为要提供给无序系列的自定义类型定义自定义哈希函数。