首页 > 解决方案 > 我如何确定一个模板类是否是另一个模板类的子类,因为模板可能不同?

问题描述

考虑以下类结构:

template <typename TType>
struct Base {public: virtual ~Base() {} };

template <typename TType>
struct Child : Base<TType> {};

template <template<typename> class Node, typename TType>
bool type(Node <TType>* node){
   return dynamic_cast<Base<TType>*>(node) == nullptr;
}

int main(){
   Child<int> child;
   type(&child);
}

只要孩子在转换前后具有相同的模板类型,此代码就可以正常工作。如果不是这种情况,它当然会失败。如果它们有不同的类型并且我提供了继承模板的特定类型,它会起作用,但我有大量可能的模板。我的第一反应是添加另一个模板:

template <template<typename TType> class Node, typename TType, typename TType2>
bool type(Node <TType>* node){
   return dynamic_cast<Base<TType2>*>(node) == nullptr;
}

这将给出一个错误“无法推断模板参数”,因为编译器不知道它是哪种类型,因为没有传递相应的参数(但我无法事先提供)。

有什么解决办法吗?我也对 dynamic_cast 以外的其他可能性持开放态度,因为我的实际目标是,如果模板化节点是模板化基类的子类。

我尝试了例如 is_base_of 没有成功。由于参数中的类型为 msimatch,围绕行的某些内容is_base_of<Base, typeid(child)>::value不起作用。

标签: c++templatestypesdynamic-cast

解决方案


您可能会使用重载:

template <typename T>
constexpr std::true_type IsBaseT(const Base<T>*) { return {}; }

constexpr std::false_type IsBaseT(const void*) { return {}; }

演示

这假设了可访问的、明确的基础。结果基于静态类型。

所以你可以把它变成一个特征:

template <typename T>
std::true_type IsBaseTImpl(const Base<T>*); // No impl
std::false_type IsBaseTImpl(const void*); // No impl

template <typename T>
using IsBaseT = decltype(IsBaseTImpl(std::declval<T*>()));

还有一个更通用的形式:

template <template <typname> C, typename T>
std::true_type IsCTImpl(const C<T>*); // No impl
template <template <typname> C>
std::false_type IsCTImpl(const void*); // No impl

template <template <typname> C, typename T>
using IsCT = decltype(IsCTImpl<C>(std::declval<T*>()));

template <typename T>
using IsBaseT = IsCT<Base, T>;

推荐阅读