1

假设我有以下非常简单的 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,传递BaseB,对于虚拟类,传递VirtualBaseB. 当然,问题在于它们采用不同数量的参数(Base需要派生类的类型),我无法提出可行的解决方案。

那么,我将如何在编译时选择基类?或者,如果这太复杂/不可能,那么拥有类的静态(CRTP)和动态(虚拟)版本的最简单方法是什么,否则实现是相同的?

4

1 回答 1

2

最简单的方法大概就是将“class D”作为VirtualBase的一个未使用的模板参数添加,使其符合相同的接口。

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

template <class D, class T> class VirtualBaseWrapper : public VirtualBase<T>{}
于 2013-02-03T10:46:17.957 回答