选择要派生的CRTP基类

时间:2013-02-03 10:30:30

标签: c++ templates crtp static-polymorphism

让我们说我有以下非常简单的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)和动态(虚拟)版本,否则实现是相同的?

1 个答案:

答案 0 :(得分:2)

最简单的方法可能只是将“D类”添加为VirtualBase的未使用模板参数,以使其符合相同的接口。

如果无法更改VirtualBase,可以使用中间模板:

template <class D, class T> class VirtualBaseWrapper : public VirtualBase<T>{}