协变返回类型,常数和不完整类 [英] Covariant return types, const-ness, and incomplete classes
问题描述
此代码在g ++ 6.1下可以成功编译,但是在clang 3.8中给出了错误:
This code compiles successfully under g++ 6.1 but gives an error with clang 3.8:
class C;
class Base {
public:
virtual const C *getC();
};
class Derived : public Base {
public:
virtual C *getC();
};
来自clang的错误如下:
The error from clang is as follows:
$ dev/compilers/linux-x86_64-2.12.2/clang3.8/bin/clang++ -Wall -c testcovariantreturn.cxx
testcovariantreturn.cxx:10:20: error: return type of virtual function 'getC' is not covariant with the return type of the function it overrides ('C' is incomplete)
如果C类是完全定义的,而不是前向声明的,则没有错误.我的理解是,当覆盖虚拟方法时,协变量允许较少"的cv限定(即,从返回类型中删除const).
If class C is completely defined rather than forward-declared, there is no error. My understanding is that covariant allows "lesser" cv-qualification (ie, dropping the const from the return type) when overriding a virtual method.
clang是否正确/是否允许要求完整的类型?如果是,为什么?在这里拥有C的定义如何改变?
Is clang correct / allowed to require a complete type, and if so, why ? How can having the definition of C available change anything here ?
这不是完全学术性的,在一个大的代码库中,我不愿意添加不必要的包含,我们尝试将声明作为标准做法.
This is not totally academic, in a large code base I am reluctant to add in unnecessary includes, we try to forward declare as standard practice.
推荐答案
这是clang 3.8错误,特别是 26297 .摘自[class.virtual],摘录自N4594:
This is clang 3.8 bug, specifically 26297. From [class.virtual], wording from N4594:
覆盖函数的返回类型应与覆盖函数的返回类型相同或协变以及函数的类别.如果函数
D :: f
覆盖函数B :: f
,则返回类型如果满足以下条件,则这些函数是协变的:(7.1)—两者都是指向类的指针,都是对类的左值引用,或者都是对右值的引用类
(7.2)—返回类型为B :: f
的类与返回类型为D :: f
的类相同,或者为返回类型为D :: f
的类的明确且可访问的直接或间接基类(7.3)—指针或引用具有相同的cv限定符,并且返回类型为D :: f
的类类型与B :: f
的返回类型中的类类型具有相同的cv限定或更少的cv限定.
The return type of an overriding function shall be either identical to the return type of the overridden function or covariant with the classes of the functions. If a function
D::f
overrides a functionB::f
, the return types of the functions are covariant if they satisfy the following criteria: (7.1) — both are pointers to classes, both are lvalue references to classes, or both are rvalue references to classes
(7.2) — the class in the return type ofB::f
is the same class as the class in the return type ofD::f
, or is an unambiguous and accessible direct or indirect base class of the class in the return type ofD::f
(7.3) — both pointers or references have the same cv-qualification and the class type in the return type ofD::f
has the same cv-qualification as or less cv-qualification than the class type in the return type ofB::f
.
具有 B :: f
返回 C const *
和 D :: f
返回 C *
匹配所有这些要求(两个指针都不具有cv限定符,并且 D :: f
的类类型不具有cv限定符而不是基类),因此应允许使用它.
Having B::f
return C const*
and D::f
return C*
matches all of these requirements (neither pointer is cv-qualified, and the class type of D::f
is less cv-qualified than the base), hence it should be allowed.
没有完整性要求; C
不需要完整来检查这些条件.
There is no requirement on completeness; C
does not need to be complete to check that these criteria.
这篇关于协变返回类型,常数和不完整类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!