给出代码:
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
是正确的方向,但是我不知道如何使它与基础的未知类型参数一起工作。
答案 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&>()));