如何检查可能使用SFINAEtypes的字段存在?

我有一个名为Traits的结构,它是Ttypes的模板,Traits有一个叫做Size的字段。 当T实际上有一个名为Size的字段时,代码会编译并且一切正常。 但是,当T是一个本地types,它显然没有大小字段和代码无法编译

template <class T> struct Traits { static const size_t Size = T::Size; }; 

我试图用SFINAE写它,但它仍然不会编译

 template <class T> struct Traits { static typename std::enable_if<!std::is_fundamental<T>::value, const size_t>::type Size = T::Size; static typename std::enable_if< std::is_fundamental<T>::value, const size_t>::type Size = sizeof(T); }; 

编译错误是

 error : redeclaration of `typename std::enable_if<std::is_fundamental<T>::value, const unsigned int>::type Traits<T>::Size' 

这是没有任何意义的,因为编译器认为我是重新声明大小,但实际上这是不可能的,因为T是基本types或不,所以我期望大小只声明一次。

任何想法是什么错误或如何规避这个问题? (使用gcc 4.8.3)

SFINAE只在某些情况下工作,这不是其中之一。 SFINAE只能用于类模板特化和函数模板签名的上下文中。 将测试移动到类模板专业化,它应该按预期工作:

 template <class T, class = void> struct Traits //default is is fundamental { static const size_t Size = sizeof(T); }; template<class T> struct Traits<T,std::enable_if_t<!std::is_fundamental<T>::value>>{ //if SFINAE does not remove this it is not fundamental and should have a T::Size static const size_t Size = T::Size; } 

直接测试T是否使用void_t嵌套Size可能会更好:

 template<typename T> using void_t = void; template <class T, class = void> struct Traits //default { static const size_t Size = sizeof(T); }; template<class T> struct Traits<T,void_t<decltype(T::Size)>>{ //if SFINAE does not remove this T::Size exists static const size_t Size = T::Size; }