C++ std::是模板类的基础吗

C++ std::是模板类的基础吗,c++,templates,c++11,C++,Templates,C++11,当a是模板类时,是否有方法测试std::Is_base_of template <typename X, typename Y> class A {}; template <typename X> class B : public A<X, char> {}; 模板类A{}; 模板类B:公共A{}; 我想静态地测试一些东西,比如,std::is\u base\u的意思是,B派生自A的任何专门化。 (为了更一般化,假设我们不知道B专门化A,即B从A派生)

a
是模板类时,是否有方法测试
std::Is_base_of

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

template <typename X> class B : public A<X, char> {};
模板类A{};
模板类B:公共A{};
我想静态地测试一些东西,比如,
std::is\u base\u的
意思是,
B
派生自
A
的任何专门化。 (为了更一般化,假设我们不知道
B
专门化
A
,即B从A派生)


一种解决方法是从一个(非模板)类派生一个,比如说
C
,然后检查
std::is\u base\u of
。但是还有其他方法吗?

您可以执行以下操作:

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*>()));

以下解决方案适用于受保护的继承

template <template <typename...> class BaseTemplate, typename Derived, typename TCheck = void>
struct test_base_template;

template <template <typename...> class BaseTemplate, typename Derived>
using is_base_template_of = typename test_base_template<BaseTemplate, Derived>::is_base;

//Derive - is a class. Let inherit from Derive, so it can cast to its protected parents
template <template <typename...> class BaseTemplate, typename Derived>
struct test_base_template<BaseTemplate, Derived, std::enable_if_t<std::is_class_v<Derived>>> : Derived
{
    template<typename...T>
    static constexpr std::true_type test(BaseTemplate<T...> *);
    static constexpr std::false_type test(...);
    using is_base = decltype(test((test_base_template *) nullptr));
};

//Derive - is not a class, so it is always false_type
template <template <typename...> class BaseTemplate, typename Derived>
struct test_base_template<BaseTemplate, Derived, std::enable_if_t<!std::is_class_v<Derived>>>
{
    using is_base = std::false_type;
};
模板
结构测试基础模板;
模板
使用is_base_template_of=typename test_base_template::is_base;
//派生-是一个类。让我们从派生继承,这样它就可以强制转换到受保护的父级
模板
结构测试基础模板:派生
{
模板
静态constexpr标准::真_型测试(基本模板*);
静态constexpr标准::假_型试验(…);
使用is_base=decltype(test((test_base_template*)nullptr));
};
//派生-不是一个类,因此它总是false_类型
模板
结构测试\基础\模板>
{
使用is_base=std::false_类型;
};
令人惊讶的是,在VS2017上,它可以处理来自同一模板的多重继承,比如C< int>和C都是。(不知道怎么做!)

检查

基于叶甫根尼·马蒙托夫的回答,我认为正确的解决方案是

template <template <typename...> class BaseTemplate, typename Derived>
struct test_base_template<BaseTemplate, Derived, std::enable_if_t<std::is_class_v<Derived>>> : Derived
{
    template<typename...T>
    static constexpr std::true_type test(BaseTemplate<T...> *);
    static constexpr std::false_type test(...);
    using is_base = decltype(test((Derived *) nullptr));
};
模板
结构测试基础模板:派生
{
模板
静态constexpr标准::真_型测试(基本模板*);
静态constexpr标准::假_型试验(…);
使用is_base=decltype(test((派生*)nullptr));
};

在这里参加聚会有点晚,但我想给出上面的一个变体

template < template <typename...> class Base,typename Derived>
struct is_base_of_template
{
    // A function which can only be called by something convertible to a Base<Ts...>*
    // We return a std::variant here as a way of "returning" a parameter pack
    template<typename... Ts> static constexpr std::variant<Ts...> is_callable( Base<Ts...>* );

    // Detector, will return type of calling is_callable, or it won't compile if that can't be done
    template <typename T> using is_callable_t = decltype( is_callable( std::declval<T*>() ) );

    // Is it possible to call is_callable which the Derived type
    static inline constexpr bool value = std::experimental::is_detected_v<is_callable_t,Derived>;

    // If it is possible to call is_callable with the Derived type what would it return, if not type is a void
    using type = std::experimental::detected_or_t<void,is_callable_t,Derived>;
};

template < template <typename...> class Base,typename Derived> 
using is_base_of_template_t = typename is_base_of_template<Base,Derived>::type;

template < template <typename...> class Base,typename Derived>
inline constexpr bool is_base_of_template_v = is_base_of_template<Base,Derived>::value;
template