让我们说我有以下非常简单的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派生(如果我想要模拟&#39;动态&#39;绑定)或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)和动态(虚拟)版本,否则实现是相同的?
答案 0 :(得分:2)
最简单的方法可能只是将“D类”添加为VirtualBase的未使用模板参数,以使其符合相同的接口。
如果无法更改VirtualBase,可以使用中间模板:
template <class D, class T> class VirtualBaseWrapper : public VirtualBase<T>{}