使用基类模板检测is_base_of

时间:2018-08-18 16:54:23

标签: c++ templates c++14

给出代码:

template<typename T, typename Other = SomeDefault>
struct Cat { ... };

template<typename T>
struct Bengal : Cat<T> { ... };

template<typename T>
struct Persian : Cat<T, Something> { ... };

struct Siberian : Cat<int> { ... };

我如何实现特征is_cat<T>,以便

  • is_cat<Cat<int, float>>is_cat<Bengal<double>>is_cat<Persian<std::string>>is_cat<Siberian>std::true_type
  • is_cat<double>(以及其他不相关的类型)为std::false_type

我认为std::is_base_of是正确的方向,但是我不知道如何使它与基础的未知类型参数一起工作。

1 个答案:

答案 0 :(得分:2)

std::is_base_of在这里无济于事,仅检查具体的基类是否为基类。但是我们不是在寻找具体的基础,而是在寻找基类模板。为此,我们可以利用重载解析:

std::false_type is_cat_impl(...);
template <typename T, typename U>
std::true_type is_cat_impl(Cat<T,U>*);

template <typename T>
using is_cat = decltype(is_cat_impl(std::declval<T*>()));

对于Cat<T,U>来说,Cat<T,U>*...更好,对于其他任何东西,它都不是匹配。


如果您也想匹配Siberian const&,那么,正如Oliv建议的那样,最好使用引用而不是指针:

std::false_type is_cat_impl(...);
template <typename T, typename U>
std::true_type is_cat_impl(Cat<T,U> const volatile&);

template <typename T>
using is_cat = decltype(is_cat_impl(std::declval<T&>()));