简体   繁体   English

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

[英]Specialize template based on whether a specific member exists

I want to write a trait that returns the integral type (float, int, char...) of a given type. 我想写一个特征,该特征返回给定类型的整数类型(float,int,char ...)。 Base is: 基数是:

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>{}

And I want it to return double for: 我希望它为以下项返回双精度值:

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

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

This does not work. 这是行不通的。 I have to merge the first and 2nd declaration like that: 我必须像这样合并第一个和第二个声明:

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 >{};

But what now, if a user of my library has types with members named "MyType" instead of "type"? 但是现在,如果我的图书馆的用户所拥有的类型的成员名为“ MyType”而不是“ type”,该怎么办? How could I make it possible to specialize this on structs like: 我如何才能专门针对以下结构:

struct foobar{
  using MyType = double;
}

Is this even possible? 这有可能吗? Actually looks like it should work with SFINAE 实际上看起来应该与SFINAE一起使用

You can do this using void_t : 您可以使用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>{};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM