std :: is_base_of用于模板类

Sas*_*dhi 13 c++ templates c++11

有没有办法测试std::is_base_of<A, B>何时A是模板类?

template <typename X, typename Y> class A {};

template <typename X> class B : public A<X, char> {};
Run Code Online (Sandbox Code Playgroud)

我想静态地测试类似的东西,std::is_base_of<A, B<int>>意思B是从任何专业化中衍生出来的A.(为了使它更通用,让我们说我们不知道B专门的方式A,即B <X>派生自A <X,char >)

解决的一种方法是从(非模板)类派生A C,然后检查std::is_base_of<C, B<int>>.但还有另一种方法吗?

Jar*_*d42 16

您可以执行以下操作:

template <template <typename...> class C, typename...Ts>
std::true_type is_base_of_template_impl(const C<Ts...>*);

template <template <typename...> class C>
std::false_type is_base_of_template_impl(...);

template <typename T, template <typename...> class C>
using is_base_of_template = decltype(is_base_of_template_impl<C>(std::declval<T*>()));
Run Code Online (Sandbox Code Playgroud)

现场演示

但是会因多重继承或私有继承而失败A.

使用Visual Studio 2017,当基类模板具有多个模板参数时,这将失败,并且无法推断 Ts...

演示

VS Bug报告

重构解决了VS的问题.

template < template <typename...> class base,typename derived>
struct is_base_of_template_impl
{
    template<typename... Ts>
    static constexpr std::true_type  test(const base<Ts...> *);
    static constexpr std::false_type test(...);
    using type = decltype(test(std::declval<derived*>()));
};

template < template <typename...> class base,typename derived>
using is_base_of_template = typename is_base_of_template_impl<base,derived>::type;
Run Code Online (Sandbox Code Playgroud)

现场演示

  • 我得到了相同的解决方案,但这个解决方案也__fails__(而不是返回`false`)与来自`A`的单一非公共继承:( (2认同)
  • @ Jarod42:谢谢!这很聪明. (2认同)
  • 看来你在`is_base_of_template_impl`中不需要`typename T`? (2认同)
  • @Sprite:不幸的是,我们没有语法来一般处理类型和非类型模板参数之间的问题。您必须创建类似的特征来处理“std::array”类型。 (2认同)