【问题标题】:Template specialization and const qualifier on type类型上的模板特化和 const 限定符
【发布时间】:2015-12-17 17:56:28
【问题描述】:

为什么编译器期望在(具体)类型Tconst T 上单独专门化模板?让我举个例子。我有一个由类类型 Key

键入的无序映射
std::unordered_map<Key, Value> data;

为了编译它必须将 std::hash 专门化为 Key 类型

namespace std {
  template<>
  class hash<Key> { /* implementation */ };
}

但是,当我将地图类型更改为

std::unordered_map<const Key, Value> data;

编译器没有使用我的特化,而是选择了通用的std::hash&lt;T&gt;,这只不过是一个编译时断言,直到我特化了std::hash&lt;const Key&gt;

撇开使用const 限定映射键类型的实用性不谈,为什么在这种情况下寻找专业化时const T 不折叠为T

另外,模板类std::hash(技术上)是否可以设计成允许这样的崩溃?

【问题讨论】:

  • 仅仅是因为Tconst T 在定义上是不同的类型(除非T 已经是const)。 std::hash 可以被设计成这样折叠,是的,但显然不是。还是个好问题!
  • std::unordered_map&lt;const std::string, int&gt; 也不编译。因此,您不需要自定义键类型来注意到问题。但通常情况下,不需要在std::{unordered_,}{multi,}map 中使用显式的const 类型,因为键始终是const
  • @rici:关于string 键的好点!至于密钥类型的 const-ness,我确实同意,但这不是我的重点。
  • @kkm:明白。我将评论提升为答案;希望它以某种方式有所帮助。如果你想要std::unordered_map&lt;const Key, Val&gt;,你总是可以明确说明哈希参数:std::unordered_map&lt;const Key, Val, std::hash&lt;Key&gt;&gt; 可以正常工作。答案中提出了更通用的解决方案。

标签: c++ c++11


【解决方案1】:

我无法真正回答“为什么”,因为这是标准委员会的决定,他们无疑有自己的理由。

问题不限于自定义类型。你也不能实例化std::unordered_map&lt;const std::string, int&gt;

当然,使用显式const 类型作为标准关联容器的键类型很少有用,因为容器的value_type 是std::pair&lt;const Key, Val&gt;;无论其声明的类型如何,键都是 const 。但我知道这与原始问题无关,volatile 限定符会产生相同的效果。

可能是其他情况吗?当然。甚至没有那么难:

template<typename Key,
         typename Val,
         typename Hash  = std::hash<typename std::remove_cv<Key>::type>,
         typename KeyEq = std::equal_to<Key>,
         typename Alloc = std::allocator<std::pair<const Key, Val>>>
using my_unordered_map = std::unordered_map<Key, Val, Hash, KeyEq, Alloc>;

唯一的区别是在Hash 模板参数的默认模板参数中使用std::remove_cv

(Live on coliru.)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多