【发布时间】:2018-06-19 21:33:10
【问题描述】:
我试图使用 Curiously Recurring Template Pattern 实现静态多态性,但我注意到 static_cast<> 通常在编译时检查一个类型是否真的可以转换为另一个类型,但它漏掉了一个错字在基类声明中,允许代码将基类向下转换为它的同级之一:
#include <iostream>
using namespace std;
template< typename T >
struct CRTP
{
void do_it( )
{
static_cast< T& >( *this ).execute( );
}
};
struct A : CRTP< A >
{
void execute( )
{
cout << "A" << endl;
}
};
struct B : CRTP< B >
{
void execute( )
{
cout << "B" << endl;
}
};
struct C : CRTP< A > // it should be CRTP< C >, but typo mistake
{
void execute( )
{
cout << "C" << endl;
}
};
int main( )
{
A a;
a.do_it( );
B b;
b.do_it( );
C c;
c.do_it( );
return 0;
}
程序的输出是:
A
B
A
为什么演员表工作没有错误?如何进行编译时检查以帮助解决此类错误?
【问题讨论】:
-
您可以
static_cast到派生类。您无法在编译时检查运行时类型。 -
@MooingDuck,这很好,但它不会像问题中那样传递错误的派生类型。但要抓住这一点,我认为无论如何都必须在语言中支持 CRTP(例如,mixins)。
-
哦,哎呀。你说得对。出于某种原因,我认为其中一个是 C,但它们都是 A。也许如果一个变体进入 derived 类?
static_assert(std::is_base_of<CRTP<decltype(this)>,decltype(this)>::value)? -
@MooingDuck,是的,我认为这是你今天能得到的最好的。使用元类,我相信您至少可以拥有某种
crtp<CRTP> C { ... };并且根本不需要手动继承。也就是说,我认为元类更适合将所需的 mixins 组合成一个新的元类或一些通用的with_mixins<...> Foo { ... }; -
A和C都派生自CRTP<A>,因此static_cast允许从CRTP<A>到其中任何一个。转换为不相关(或模棱两可)的类型,例如不过,B需要进行诊断。
标签: c++ static-cast class-template static-polymorphism