Invalid covariant type with CRTP clonable class
我正在尝试用crtp实现一个可克隆类。但是,我需要有一个抽象类,它有一个纯虚拟克隆方法,由子类重写。为了实现这一点,我需要克隆函数返回协变返回类型。我在下面编写了这段代码,编译器对我大喊这个错误:
1 | main.cpp:12:5: error: return type of virtual function 'clone' is not covariant with the return type of the function it overrides ('B *' is not derived from 'AbstractClonable *') |
类"b"似乎是可抽象的子类,甚至是双向的!我怎么解决这个问题?非常感谢你。我试过使用Clang 3.6和GCC 4.9.2。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | struct AbstractClonable { virtual AbstractClonable* clone() const = 0; }; template<typename T> struct Clonable : virtual AbstractClonable { T* clone() const override { return new T{*dynamic_cast<const T*>(this)}; } }; struct A : virtual AbstractClonable { }; struct B : A, Clonable { }; |
是的,
C++ 14×103/8:
If the class type in the covariant return type of
D::f differs from that ofB::f , the class type in the return type ofD::f shall be complete at the point of declaration ofD::f or shall be the class typeD .
类具有在协变返回类型中使用自身的特殊权限。其他类,包括crtp基,需要等到类完成后再声明协变函数。
您可以使用非虚拟接口习惯用法(nvi)来解决此问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class AbstractClonable { protected: virtual AbstractClonable* do_clone() const = 0; public: AbstractClonable *clone() const { return do_clone(); } }; template<typename T> class Clonable : public virtual AbstractClonable { Clonable* do_clone() const override { // Avoid using T in this declaration. return new T{*dynamic_cast<const T*>(this)}; } public: T *clone() const { // But here, it's OK. return static_cast< T * >( do_clone() ); } }; |
即使
1 | B* clone() const override |
当然,这不是对
解决方法(但实际上与您想要的不同)是定义
1 | Clonable* clone() const override |
在
1 2 3 4 5 | template<typename T> T* clone(const T* object) { return static_cast<T*>(object->clone()); } |
相关:派生出奇怪的循环模板和协方差
我想问题是
1 2 3 | T* clone() const override{ return new T{*dynamic_cast<const T*>(this)}; } |
返回b*而不是abstractClonable*。