假设我有以下非常简单的 CRTP 基类:
template< class D, class T >
struct Base
{
T foo()
{
return static_cast< D* >(this)->foo_i();
}
};
而且,少数派生类。一切运行良好,但存在一个问题:在一种特殊情况(或者可能是几种情况)中,我真的非常非常希望两个类具有运行时多态行为(需要将它们放入容器中)。换句话说,我希望一些派生 CRTP 类也具有虚拟版本。所以,我想出了以下课程:
template< class T >
struct VirtualBase : public Base< VirtualBase< T >, T >
{
virtual T foo_i() = 0;
};
现在,在我需要运行时多态性的地方,我只是从这个类派生而来。假设我希望我的派生类DerivedB
有一个虚拟版本。香草 DerivedB 看起来像这样:
template< class T >
struct DerivedB : public Base< DerivedB< T >, T >
{
T foo_i()
{
std::cout << "I'm special!\n";
return T();
}
};
我想做的基本上是向此类添加一个额外的模板参数,以便我可以在编译时选择是从 Base 派生(如果我想要模拟的“动态”绑定)还是 VirtualBase(如果我想要真正的动态绑定)。类似于以下伪 C++ 的东西:
template< class B, class T >
struct DerivedB : public B< DerivedB< T >, T >
{
T foo_i()
{
std::cout << "I'm special!\n";
return T();
}
};
因此,对于普通的 CRTP,传递Base
为B
,对于虚拟类,传递VirtualBase
为B
. 当然,问题在于它们采用不同数量的参数(Base
需要派生类的类型),我无法提出可行的解决方案。
那么,我将如何在编译时选择基类?或者,如果这太复杂/不可能,那么拥有类的静态(CRTP)和动态(虚拟)版本的最简单方法是什么,否则实现是相同的?