c++ - tabla - reglas de los identificadores en programacion
Discrepancia del compilador de nombre de clase inyectada (3)
Considere este código:
struct foo{};
int main() {
foo::foo a;
}
Espero que esto esté bien formado, declarando una variable de tipo foo
por la regla en [clase] / 2 (N4140, énfasis mío):
Se inserta un nombre de clase en el ámbito en el que se declara inmediatamente después de ver el nombre de clase . El nombre de la clase también se inserta en el alcance de la clase en sí ; Esto se conoce como el nombre de clase inyectado . Para fines de verificación de acceso, el nombre de clase inyectada se trata como si fuera un nombre de miembro público.
clang 3.6.0
está de acuerdo conmigo, compilando el código anterior sin advertencias aplicables con -Wall -pedantic
.
gcc 5.2.0
no está de acuerdo, con el siguiente mensaje de error:
main.cpp: In function ''int main()'':
main.cpp:5:5: error: ''foo::foo'' names the constructor, not the type
foo::foo a;
Lo anterior es válido sin importar qué tan profundo sea el anidamiento de los nombres de clase inyectados, por ejemplo, foo::foo::foo::foo
.
¿Hay alguna regla que obligue a que la construcción se interprete como un constructor en ese contexto o es un error de gcc
? ¿O estoy interpretando las normas de forma incorrecta?
Creo que este es el tema del defecto de idioma # 147 que contiene este ejemplo
class B { };
class A: public B {
A::B ab; // B is the inherited injected B
A::A aa; // Error: A::A is the constructor
};
Al menos gcc parece creer eso. :-)
Parece que clang
está mal en este caso. La excepción relevante que estaba buscando está en [class.qual] / 2:
2 En una búsqueda en la que los nombres de función no se ignoran y el especificador de nombre anidado nomina a una clase C:
(2.1) si el nombre especificado después del especificador de nombre anidado, cuando se busca en C, es el nombre de clase inyectado de C , o
[...]
en cambio, se considera que el nombre nombra al constructor de la clase C.
El estándar tiene un ejemplo casi equivalente (no normativo, obviamente):
struct A { A(); };
struct B: public A { B(); };
A::A() { }
B::B() { }
B::A ba;// object of type A
A::A a;// error, A::A is not a type name
struct A::A a2;// object of type A
Sin embargo, clang
emite un diagnóstico correcto en este caso:
error: qualified reference to ''A'' is a constructor name rather than a type wherever a constructor can be declared
Quizás clang
interpreta la línea In a lookup in which function names are not ignored
como In a lookup in which a constructor declaration is valid
, pero eso no parece ser una interpretación correcta.
Hay un error existente para esto en el clang
bugzilla.
Relevante, pero no una respuesta: la gente del CCG discutió exactamente esto durante años y pensó que no debía aceptarse. Hicieron explícitamente esto un error en GCC 4.5 y más reciente, en 4.4.7 fue aceptado.
BTW: Probablemente quieras usar Clang''s -Weverything
lugar de -Wall -pedantic
al investigar tales cosas.