对模板使用dynamic_cast

using dynamic_cast with templates

本文关键字:dynamic cast      更新时间:2023-10-16

在c++中实现基于模板的工厂时,我创建了以下allocator函数来实例化给定的子类:

template<class ChildClass, class ParentClass>
ParentClass* allocator() {
   ChildClass *child  = new ChildClass();
   ParentClass*parent = dynamic_cast<ParentClass*>(child);
   if(NULL==parent) {
     delete child;
     return NULL;
   }
   return parent;
}

一切正常,但是当通过静态代码分析工具(如coverity)运行代码时,delete child;行被标记为逻辑死代码

我做运行时检查的原因是断言ChildClass是从ParentClass派生出来的。

现在我明白了,在模板扩展期间,编译器已经知道ChildClass是否从ParentClass派生,而dynamic_cast仅在运行时计算。

所以运行时检查逻辑上是死代码,如果ChildClass确实是从ParentClass派生的(在这种情况下,如果ChildClass已经成功分配,dynamic_cast将始终返回non-NULL)。

但是是否有办法确保ChildClass在编译时(模板扩展时间)从ParentClass派生?

在c++中,模板和继承是不相关的,但我可能遗漏了一些明显的东西。

的限制

不幸的是,代码应该在旧的编译器上编译(例如,Visual Studio 6附带的c++实现),这排除了任何新的扩展,如C++11 -features

您可以使用std::is_base_of:

constexpr bool is_base = std::is_base_of<ParentClass, ChildClass>::value;

ChildClass不是从ParentClass派生的时候,你可以在static_assert中使用这个来表示编译器错误。

static_assert(std::is_base_of<ParentClass, ChildClass>::value,
              "ParentClass is not base of ChildClass");

如果你没有c++ 11的支持,你可以使用boost::is_base_ofBOOST_STATIC_ASSERT

如果"Derived"继承自"Base",那么"Derived"类型的指针可以赋值给指向"Base"类型的指针。例如:

void AssignToBase(Derived* derived) {
  Base* base = derived;
} 

…以上成功编译证明了"Derived"继承自"Base"。您可以将它与SFINAE和静态断言(无论是在c++ 11中还是使用Boost的静态断言机制)结合使用,以验证派生类是否继承自父类。正如juanchopanza所指出的,c++ 11提供了一个简单的std::is_base_of<>类型特征类,您可以使用它来测试这种继承关系。