使用SFINAE检查类型是否完整

时间:2014-01-14 16:57:17

标签: c++ c++11 metaprogramming sfinae

如果完全定义了类型,是否可以使用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");

解决方案不应修改哈希结构

3 个答案:

答案 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>,但只能有一个定义。但如果您稍后定义Tis_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专家,所以我可能错过了使用新功能的一些要点。在那种情况下随意火,我会尝试纠正答案。