带有CRTP可克隆类的无效协变量类型
Invalid covariant type with CRTP clonable class
我正在尝试使用CRTP实现一个可键入的类。但是,我需要拥有具有纯虚拟克隆方法的抽象类,该方法被儿童课覆盖。为了实现这一目标,我需要克隆函数才能返回协变量返回类型。我在下面制作了此代码,编译器对我大喊这个错误:
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
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<B> {
};
即使B
确实是从Clonable<B>
派生的,这里的问题是Clonable<B>
构造无效,因为它定义了
B* clone() const override
当然,哪个不是AbstractClonable::clone()
的覆盖,因为编译器此时还没有看到B
的CC_5。因此,我相信这个问题是因为编译器无法构建Clonable<B>
的CC_7基础。
解决方法(但与您想要的不一样)是定义
Clonable* clone() const override
在Clonable
中。正如您在评论中提到的那样,您也可以定义免费功能
template<typename T>
T* clone(const T* object)
{
return static_cast<T*>(object->clone());
}
相关:奇怪的重复模板和协方差
是的, B
是从 AbstractClonable
派生的,但是编译器不知道在Clonable<B>
的实例化过程中,因为B
仍然不完整。
C 14§10.3/8:
如果
D::f
的协变返回类型与B::f
的返回类型不同,则在D::f
的返回类型中的类类型应在D::f
声明时完成,或者应为类型D
。
班级有特殊许可,可以在协变返回类型中使用自身。其他类,包括CRTP基地,需要等到课程完成后才声明协变功能。
您可以使用非虚拟界面成语(NVI)解决问题:
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() );
}
};
我认为问题是
T* clone() const override{
return new T{*dynamic_cast<const T*>(this)};
}
返回b *而不是抽象clonable *。
相关文章:
- 如果用户输入无效,如何使用字符串变量-C++重复输入命令
- 声明为无效的变量或字段'...' Ardunio 编译器上的错误
- 对全局变量的非常量引用的初始化无效
- std::move 如何使原始变量的值无效?
- (C++) 从另一个类访问变量时值无效
- 错误:变量或字段'PrintEntity'声明无效无效打印实体(实体 e);
- C++ SPDLOG 编译错误:变量或字段"set_error_handler"声明为无效
- 将非静态成员函数C 的使用无效,而将成员功能作为函数变量
- 没有变量声明为函数,但错误:二进制表达式的操作数无效
- 我收到错误"变量类型不完整"无效,我找不到问题所在
- 声明为无效的变量或字段'name of var'
- 错误:非静态数据成员的使用无效,在此范围内未声明变量
- 使用const变量时,非静态数据成员的使用无效
- 常量 & 指非易失性变量。变量将更改。更改是否使常量 & 无效?
- 将流定义为私有类变量似乎在Linux下有效,但在WindowsVisualStudio下无效
- 声明为无效的变量或字段'Function'
- 使用 valgrind 时获得 int 变量指针的无效读取大小错误
- C++错误"变量或字段声明为无效"
- 带有CRTP可克隆类的无效协变量类型
- 将成员枚举变量传递给类构造函数时出现无效的重定义错误