我有一个名为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; }