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
结构是模板的基础
{
//只能由可转换为基的对象调用的函数*
//我们在这里返回一个std::variant,作为“返回”参数包的一种方式
模板static constexpr std::variant可调用(Base*);
//检测器,将返回调用的类型是可调用的,或者如果无法完成,它将不会编译
使用is_callable_t=decltype(is_callable(std::declval())的模板;
//是否可以调用派生类型为的Is_callable
静态内联constexpr bool value=std::experional::是否检测到;
//如果可以使用派生类型调用is_callable,那么它将返回什么,如果不是,则类型为void
使用类型=标准::实验::检测到\u或\u t;
};
模板<模板类基,类型名派生>
using is_base_of_template_t=typename is_base_of_template::type;
模板<模板类基,类型名派生>
inline constexpr bool是\u template的\u base\u\v=是\u template::value的\u base\u;
这使用了建议的is_检测机制,我认为这使测试的意图更加清晰。然而,我现在可以得到在实例化基类的同时我发现有用的类型。这样我就可以写作了
template <typename T, typename U> struct Foo { };
struct Bar : Foo<int,std::string> { };
static_assert( is_base_of_template_v<Foo,Bar> );
// The variant type contains the types with which the Foo base is instantiated
static_assert( std::is_same_v<std::variant<int,std::string>,is_base_of_template_t<Foo,Bar>> );
模板结构Foo{};
结构条:Foo{};
静态断言(是模板的基础);
//变量类型包含用于实例化Foo基的类型
静态断言(std::is_same_v);
“A”不是一种类型。你不能这样做,但你可以做“std::is_base_of”类似的问题,我以前回答过。my\u is\u base\u of
对你来说是合理的用法吗?@TartanLlama谢谢。这将是非常具体的方式B专门A虽然。如果可能的话,我正在寻找一个更普遍的解决方案。@Arunmu谢谢。我明白了,这在我的环境中是可行的。嗯,我不知道Ts…
可以在这种情况下推导出来。美好的我找到了相同的解决方案,但是这个解决方案也失败了(而不是返回false
),从A
进行了单一的非公共继承:(@Jarod42:谢谢!这很聪明。似乎你不需要中的类型名t
是
?@Sprite:不幸的是,我们没有语法在类型和非类型模板参数之间进行通用处理。你必须创建与std::array
类似的特性来处理类型。你的解决方案非常好但是它有一个小错误,尝试测试静态的断言(是否是基模板的::value);谢谢。这很好!
template <typename T, typename U> struct Foo { };
struct Bar : Foo<int,std::string> { };
static_assert( is_base_of_template_v<Foo,Bar> );
// The variant type contains the types with which the Foo base is instantiated
static_assert( std::is_same_v<std::variant<int,std::string>,is_base_of_template_t<Foo,Bar>> );