c++ - Tipos de retorno covariantes, constancia y clases incompletas.
covariance (2)
Este código se compila exitosamente bajo g ++ 6.1 pero da un error con clang 3.8:
class C;
class Base {
public:
virtual const C *getC();
};
class Derived : public Base {
public:
virtual C *getC();
};
El error de clang es el siguiente:
$ 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)
Si la clase C está completamente definida en lugar de declarada hacia adelante, no hay error. Según tengo entendido, covariant permite la calificación cv "menor" (es decir, descartar la constante del tipo de retorno) al invalidar un método virtual.
¿Es correcto el clang / puede requerir un tipo completo, y si es así, por qué? ¿Cómo puede tener la definición de C disponible cambiar algo aquí?
Esto no es totalmente académico, en una base de código grande que me resisto a incluir en los innecesarios, tratamos de declarar como práctica estándar.
Este es el error de 26297 3.8, específicamente 26297 . De [class.virtual], redacción de N4594:
El tipo de retorno de una función de anulación será idéntico al tipo de retorno de la función anulada o covariante con las clases de las funciones. Si una función
D::f
anula una funciónB::f
, los tipos de retorno de las funciones son covariantes si satisfacen los siguientes criterios: (7.1): ambos son punteros a las clases, ambos son referencias de valores a las clases, o ambos son rvalue las referencias a las clases
(7.2) - la clase en el tipo de retorno deB::f
es la misma clase que la clase en el tipo de retorno deD::f
, o es una clase de base directa o indirecta no ambigua y accesible de la clase en el tipo de retorno deD::f
(7.3) - tanto los punteros como las referencias tienen la misma calificación de CV y el tipo de clase en el tipo de devolución deD::f
tiene la misma calificación de CV que la clase de clase en el tipo de devolución deB::f
.
Tener B::f
return C const*
y D::f
return C*
coincide con todos estos requisitos (ninguno de los punteros está calificado para cv, y el tipo de clase de D::f
es menos cv calificado que la base), por lo tanto debería estar permitido
No hay ningún requisito de integridad; C
no necesita estar completo para verificar que estos criterios.
Tampoco encuentro nada malo en tu código. Se compila con la versión head de clang y todos los compiladores que probé, excepto clang 3.8 y anteriores.
El texto estándar relevante:
10.3 nota 8:
Si el tipo de clase en el tipo de retorno covariante de D :: f difiere del de B :: f, el tipo de clase en el tipo de retorno de D :: f se completará en el punto de declaración de D :: f o ser la clase tipo D.
El tipo de clase de los métodos covariantes debe ser el mismo o completo, pero según tengo entendido, las diferencias constantes / volátiles todavía se consideran el mismo tipo de clase , por lo que su ejemplo es legal.