Estoy tratando de entender los siguientes fragmentos de código
Fragmento n. ° 1
template <typename T>
struct A
{
static constexpr int VB = T::VD;
};
struct B : A<B>
{
};
Ni gcc9 ni clang9 arrojan un error aquí.
P. ¿Por qué se compila este código? ¿No estamos creando instancias A<B>
cuando heredamos de B? No hay VD en B, entonces, ¿no debería el compilador arrojar un error aquí?
Fragmento # 2
template <typename T>
struct A
{
static constexpr auto AB = T::AD; // <- No member named AD in B
};
struct B : A<B>
{
static constexpr auto AD = 0xD;
};
En este caso, gcc9 compila bien pero clang9 arroja un error que dice "Ningún miembro llamado AD en B".
P. ¿Por qué se compila con gcc9 / por qué no se compila con clang9?
Fragmento # 3
template <typename T>
struct A
{
using TB = typename T::TD;
};
struct B : A<B>
{
using TD = int;
};
Aquí tanto clang9 como gcc9 arrojan un error. gcc9 dice "uso no válido del tipo incompleto 'struct B'".
P. Si la estructura B está incompleta aquí, ¿por qué no está incompleta en el fragmento n. ° 2?
Opciones del compilador usado: -std=c++17 -O3 -Wall -Werror
. ¡¡¡Gracias por adelantado!!!
fuente
struct B
instanciasA
conB
?B
está incompleto ... Pero noRespuestas:
Creo que estos esencialmente se reducen a [temp.inst] / 2 (énfasis mío):
y [temp.inst] / 9
La redacción de la norma relativa a la creación de instancias de plantilla implícita deja muchos detalles abiertos a interpretación. En general, me parece que simplemente no puede confiar en partes de una plantilla que no se instancian a menos que la especificación lo diga explícitamente. Así:
Fragmento n. ° 1
Estás creando instancias
A<B>
. Pero la creación de instanciasA<B>
solo crea instancias de las declaraciones, no las definiciones de sus miembros de datos estáticos.VB
nunca se usa de una manera que requiera una definición para existir. El compilador debe aceptar este código.Fragmento # 2
Como señaló Jarod42, la declaración de
AB
contiene un tipo de marcador de posición. Me parece que la redacción de la norma no es realmente clara sobre lo que se supone que sucederá aquí. ¿La instanciación de la declaración de un miembro de datos estáticos que contiene un tipo de marcador de posición activa la deducción del tipo de marcador de posición y, por lo tanto, constituye un uso que requiere la definición del miembro de datos estático? No puedo encontrar una redacción en el estándar que diga claramente sí o no a eso. Por lo tanto, diría que ambas interpretaciones son igualmente válidas aquí y, por lo tanto, GCC y clang tienen razón ...Fragmento # 3
Un tipo de clase solo se completa en el punto en el que llega al cierre
}
del especificador de clase [class.mem] / 6 . Por lo tanto,B
está incompleto durante la instanciación implícita deA<B>
todos sus fragmentos. Es solo que esto era irrelevante para Snippet # 1. En Snippet # 2, clang te dio un errorNo member named AD in B
como resultado. Similar al caso del Snippet # 2, no puedo encontrar la redacción sobre cuándo se instanciarían exactamente las declaraciones de alias de miembro. Sin embargo, a diferencia de la definición de miembros de datos estáticos, no existe una redacción para evitar explícitamente la creación de instancias de declaraciones de alias de miembros durante la creación de instancias implícita de una plantilla de clase. Por lo tanto, diría que el comportamiento de GCC y clang es una interpretación válida del estándar en este caso ...fuente
constexpr
miembro de datos estáticos era solo una declaración. C ++ 17 obtuvoinline
variables econstexpr
implicainline
, y esto hace que la declaración del miembro de datos estáticos en el cuerpo sea una definición.auto
caso, la regla dice que la declaración debe ser una declaración de inicialización. Este solo puede ser el caso si se sabe que la declaración es una definición (que yo sepa ... he estado fuera de la tierra de los abogados por un tiempo). En el pasado, había un caso similar y se agregó eel.is/c++draft/temp.inst#2.sentence-3 , donde una declaración que es una definición se instancia como "se sabe que es una definición" sin realmente instanciando la definición.