如果完全定义了类型,是否可以使用SFINAE进行检查?
E.g。
template <class T> struct hash;
template <> struct hash<int> {};
// is_defined_hash_type definition...
enum Enum { A, B, C, D };
static_assert ( is_defined_hash_type<int> ::value, "hash<int> should be defined");
static_assert (! is_defined_hash_type<Enum>::value, "hash<Enum> should not be defined");
解决方案不应修改哈希结构。
答案 0 :(得分:15)
您可以制作is_complete
类型特征,使用不正确的事实来评估sizeof(T)
不完整类型T
:
template <typename T>
struct is_complete_helper {
template <typename U>
static auto test(U*) -> std::integral_constant<bool, sizeof(U) == sizeof(U)>;
static auto test(...) -> std::false_type;
using type = decltype(test((T*)0));
};
template <typename T>
struct is_complete : is_complete_helper<T>::type {};
并通过确定is_defined_hash_type<T>
是否完整来使用它来检查hash<T>
。 (Live at Coliru)
丹尼尔在答案中说,这种事情的效用是有限的。特征实际上并不测试类型在您查询的代码中是否完整,它测试类型是否在程序中为特定类型首次实例化特征的位置完成。
答案 1 :(得分:5)
这是不可能的。原因是您必须定义is_defined_hash_type<T>
,但只能有一个定义。但如果您稍后定义T
,is_defined_hash_type<T>
的定义将产生不同的结果,因此定义不同,并且这是不允许的。这违反了ODR(一个定义规则)。
答案 2 :(得分:0)
到目前为止,我想出的最好的是以下内容,在typedef
的所有专业化中至少需要hash
具有通用名称:
template <class T> struct hash;
template <> struct hash<int> {
typedef int value_type;
};
template<class T>
constexpr bool is_defined_hash_type(typename hash<T>::value_type) {
return true;
}
template<class T>
constexpr bool is_defined_hash_type(T) {
return false;
}
int main()
{
static_assert ( is_defined_hash_type< int >(0), "hash<int> should be defined");
static_assert (! is_defined_hash_type< double>(0), "hash<Enum> should not be defined");
return 0;
}
由于添加了参数(需要触发SFINAE),语法非常难看。如果你认为这可能是要走的路,我会尝试进一步清理它。
免责声明:我绝不是C ++ 11专家,所以我可能错过了使用新功能的一些要点。在那种情况下随意火,我会尝试纠正答案。