c++ - ¿Por qué la deducción del tipo de devolución automática funciona con tipos no completamente definidos?
c++14 crtp (1)
Considera lo siguiente:
template<typename Der>
struct Base {
// NOTE: if I replace the decltype(...) below with auto, code compiles
decltype(&Der::operator()) getCallOperator() const {
return &Der::operator();
}
};
struct Foo : Base<Foo> {
double operator()(int, int) const {
return 0.0;
}
};
int main() {
Foo f;
auto callOp = f.getCallOperator();
}
Quiero crear una función miembro en la clase base CRTP con un tipo de devolución que depende de la firma del operator()
en la clase derivada. Sin embargo, decltype(&Der::operator())
no puede compilarse; La función miembro de operator()
en Foo
no está visible. Supongo que esto se debe a que la plantilla de la clase base se instancia antes de que Foo
esté completamente definido.
Sorprendentemente, si coloco el auto
para el tipo de retorno compila. Supuse que el auto
haría que el compilador deduzca el tipo de retorno del cuerpo de la función y falle, porque el cuerpo usa el tipo de Foo
no completamente definido.
Este comportamiento es el mismo para MSVC 2015.3 y Clang 3.8
¿Por qué el código comenzó a funcionar con auto
? ¿La deducción auto
tipo de alguna manera "retrasa" la instanciación? ¿O utilizar un contexto diferente al de una expresión de devolución escrita a mano?
Tu conjetura es correcta. Un tipo de retorno deducido no se deduce hasta que se necesita la firma de la función. Esto significa que se deducirá en el contexto de la llamada a getCallOperator
, momento en el que Foo
está completamente definido.
Esto se especifica en 7.1.6.4p12:
La deducción del tipo de devolución para una plantilla de función con un marcador de posición en su tipo declarado se produce cuando se crea una instancia de la definición, incluso si el cuerpo de la función contiene una declaración de devolución con un operando no dependiente del tipo.