我有一个名为Traits的结构,它是类型为T的模板,Traits有一个名为Size的字段.当T实际上有一个名为Size的字段时,代码编译并且一切正常.但是,当T是本机类型时,它显然没有Size字段,并且代码无法编译
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'
这没有任何意义,因为编译器认为我正在重新声明Size但实际上它是不可能的,因为T是基本类型或不是因此我希望Size只被声明一次.
知道什么是错的或如何规避这个问题? (使用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;
}
使用void_t直接测试T是否具有嵌套大小可能更好:
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;
}