Considere este ejemplo (viniendo de aquí ):
#include <type_traits>
#include <iostream>
template <typename U>
struct A {
};
struct B {
template <typename F = int>
A<F> f() { return A<F>{}; }
using default_return_type = decltype(std::declval<B>().f());
};
int main()
{
B::default_return_type x{};
std::cout << std::is_same< B::default_return_type, A<int>>::value;
}
Se compila sin errores en gcc9.2 pero gcc7.2 y clang 10.0.0 se quejan de B
no estar completos. El error de Clangs es:
prog.cc:11:58: error: member access into incomplete type 'B'
using default_return_type = decltype(std::declval<B>().f());
^
prog.cc:7:8: note: definition of 'B' is not complete until the closing '}'
struct B {
^
prog.cc:16:8: error: no type named 'default_return_type' in 'B'
B::default_return_type x{};
~~~^
prog.cc:17:35: error: no member named 'default_return_type' in 'B'
std::cout << std::is_same< B::default_return_type, A<int>>::value;
~~~^
c++
language-lawyer
incomplete-type
declval
idclev 463035818
fuente
fuente
.f()
. Eso tiene sentido; el tipo incompletoB
no tiene un miembrof
.std::declval
ya no importa si el tipo estaba completo o no (y supongo que estoy equivocado con eso)B
no está completo ni se considera completo enalias-declaration
.Respuestas:
La fuente del error no es el
std::declval
acceso incompleto a los miembros de la clase.Hasta que la resolución de CWG1836 se fusionó hace 2.5 años, el estándar requería que la clase se completara en una expresión de acceso de miembro de clase (
E1.E2
).[expr.ref] / 2 en C ++ 11 :
[expr.ref] / 2 en C ++ 17 :
Y una clase no se considera completa en
alias-declaration
sí mismamember-specification
.[class.mem] / 6 en C ++ 17 :
fuente
De [declive] :
Esta redacción ha estado presente desde C ++ 11 (por lo que no es posible que los compiladores se ajusten a un estándar anterior)
fuente
T
debería ser absolutamente un tipo completo. Me alegro de haber comprobado el estándar.