根据特定成员是否存在来专门化模板

时间:2015-05-28 07:47:34

标签: c++ templates types sfinae

我想编写一个返回给定类型的整数类型(float,int,char ...)的特征。基数是:

template< class T, typename T_SFINAE = void >
struct IntegralType;

template< class T >
struct IntegralType< T, std::enable_if< (std::is_integral<T>::value || std::is_floating_point<T>::value) > >{
  using type = T;
}

template< class T >
struct IntegralType<T>: IntegralType<T::type>{}

我想让它返回双倍:

struct foo{
  using type = double;
}
struct bar{
  using type = foo;
}

IntegralType<double>::type == double
IntegralType<foo>::type == double
IntegralType<bar>::type == double

这不起作用。我必须合并第一个和第二个声明:

template< typename T, bool isIntegral = (std::is_integral<T>::value || std::is_floating_point<T>::value) >
struct IntegralType{
    using type = T;
};

template< typename T >
struct IntegralType< T, false >: IntegralType< typename T::type >{};

但是现在,如果我的图书馆的用户有类型名为“MyType”而不是“type”的成员?我怎样才能在结构上专门化这个:

struct foobar{
  using MyType = double;
}

这甚至可能吗?实际上看起来它应该适用于SFINAE

1 个答案:

答案 0 :(得分:3)

您可以使用void_t执行此操作:

//void_t for evaluating arguments, then returning void
template <typename...>
struct voider { using type = void; };
template <typename... Ts>
using void_t = typename voider<Ts...>::type;

//fallback case, no valid instantiation
template< class T, typename T_SFINAE = void >
struct IntegralType;

//enabled if T is integral or floating point
template< class T >
struct IntegralType< T, std::enable_if_t< (std::is_integral<T>::value || std::is_floating_point<T>::value) > >{
  using type = T;
};

//enabled if T has a ::type member alias
template< class T >
struct IntegralType<T, void_t<typename T::type>> : IntegralType<typename T::type>{};

//enabled if T has a ::MyType member alias
template< class T >
struct IntegralType<T, void_t<typename T::MyType>> : IntegralType<typename T::MyType>{};