我想使用标准库的无序容器的默认实例创建一个类型特征来检查特定类型是否可散列,因此它是否具有std::hash
. 我认为这将是一个非常有用的功能(例如,在通用代码中std::set
用作故障保护)。std::unordered_set
因此,我认为std::hash
没有为每种类型定义,开始制作以下 SFINAE 解决方案:
template<typename T> std::true_type hashable_helper(
const T&, const typename std::hash<T>::argument_type* = nullptr);
template<typename T> std::false_type hashable_helper(...);
//It won't let me derive from decltype directly, why?
template<typename T> struct is_hashable
: std::is_same<decltype(hashable_helper<T>(std::declval<T>())),
std::true_type> {};
(如果这不是最好的解决方案甚至是错误的,请原谅我谦虚的 SFINAE 能力。)
但后来我了解到,gcc 4.7和VC++ 2012都定义std::hash
了任何类型T
,只是static_assert
在非专业版本中。但是,它们不是有条件地编译(以及使用gcc 4.7的libstdc++的clang 3.1)使断言失败,从而导致编译错误。这似乎是合理的,因为我认为s 不是由 SFINAE 处理的(对吗?),所以 SFINAE 解决方案似乎根本不可能。更糟糕的是,在通用模板中甚至没有 a但只是没有定义它static_assert
gcc 4.6
static_assert
std::hash
()
运算符,在尝试使用它时导致链接器错误(这总是比编译错误更糟糕,我无法想象有任何方法可以将链接器错误转换为编译器错误)。
那么,如果类型具有有效的特std::hash
化,或者至少对于static_assert
通用模板中的库(以某种方式将static_assert
错误转换为 SFINAE 非错误),是否有任何符合标准且可移植的方法来定义返回的这种类型特征?