我想用类型trait来检查一个特定的类型是否可以使用标准库的无序容器的缺省实例化,因此如果它具有std::hash
的有效特化。我认为这将是一个非常有用的功能(例如,在通用代码中使用std::set
作为std::unordered_set
的失败保护)。所以我想std::hash
没有为每种类型的定义,开始做以下SFINAE解决方案:(请原谅我的微薄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> {};
但然后我知道,gcc 4.7和VC++ 2012定义std::hash
任何类型T
,只是static_assert
在非专业版本。但不是有条件地编译它们(还有铛3.1使用gcc 4.7的libstdC++)导致编译错误的断言失败。这似乎是合理的,因为我认为static_assert
s不是由SFINAE处理的(对吧?),所以SFINAE解决方案似乎根本不可能。它更糟糕的是gcc 4.6
甚至在一般std::hash
模板中甚至没有static_assert
模板,但是没有定义它的()
运算符,导致尝试使用它时出现链接器错误(这总是比编译错误更糟糕,我无法想象任何方式将链接器错误转换为编译器错误)。
那么,有没有符合标准的和可移植的方式来定义这样的类型特征返回如果一个类型有一个有效的std::hash
专业化,或许至少荷兰国际集团在通用模板(在某种程度上转化static_assert
错误到库static_assert
一个SFINAE非错误)?
编辑:好吧,我对声明* VC++ *编译它是由一些不同的旧版本,其实* VC++ *行为像* GCC *,窒息了'static_assert' –
看起来像海湾合作委员会的人都知道的问题。据说Gcc 4.8没有这个静态断言,但他们考虑将来推出一个标准的实现,有点类似于Boost hash,其中实现被ADL拾取。 – Ichthyo
https://gcc.gnu.org/ml/libstdc++/2013-03/msg00029.html – Ichthyo