首页 > 解决方案 > 如何复制具有虚拟基类的模板化实例?

问题描述

TL; DR
如何复制向量的最后一个元素,因为该元素是模板类的实例,它也是从虚拟基类派生的?


我想创建一个将充当撤消堆栈的向量。堆栈应包含基于浮点数和字符串的对象(可能还有其他类型)。它可能包含所有浮点数、所有字符串或两者的组合。第一次添加浮点数或字符串时,我想将它的副本添加到堆栈中。

这是我到目前为止所拥有的:

class Base
{
...
virtual bool func1() = 0;
}

带有模板参数的派生类

template<typename T>
class derived : public base {...}

而这两个

class foo : public derived<float>
class bar : public derived<string>

主要:

std::vector<Base> stack;
if (condition) 
stack.push_back(new foo())
else
stack.push_back(new bar())

如果stack.back().func1()==true添加另一个fooor barfunc1fooand中实现,bar如果它是第一个foobar在堆栈中,则返回 true

if (stack.back().func1())  
 //do something like
 //stack.push_back(new foo) if stack.back() is a foo
 //stack.push_back(new bar) if stack.back() is a bar

现在,我不能这样做,stack.push_back(new Base)因为它有一个虚函数。出于同样的原因,我无法复制stack.back(). 我也做不到,stack.push_back(new drived<T>)因为我不知道那T是。我绝对不想硬编码new foo, new bar,string或者float因为我想为将来的派生类保留代码通用性。

那么如何复制向量的最后一个元素,或者添加一个相同类型的新元素,假设这个元素是从虚拟基类派生的模板类?

标签: c++templates

解决方案


传统上,它是通过将clone方法添加到Base

struct Base {
    virtual std::unique_ptr<Base> clone() const = 0;
    virtual ~Base() = default;
};

CRTP 可用于在此处自动覆盖此方法:

template<class Child> struct Clonable: Base {
    std::unique_ptr<Base> clone() const final {
        auto &asChild = *static_cast<Child const *>(this);
        return std::make_unique<Child>(asChild);
    }
};

struct Foo: Clonable<Foo> {};

推荐阅读