我如何确定模板化 class 是否是另一个模板化 class 的子类,因为模板可能不同?

How can I determine, if a templated class is a sublass of another templated class, as the templates might differ?

考虑以下 class 结构:

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 以外的其他可能性持开放态度,因为我的实际目标是,如果模板化节点是同样模板化的基础 class.

的子 class

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

您可能会使用重载:

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

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

Demo

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

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

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>;