dev - El programa se compila de manera diferente en 3 compiladores principales de C++. ¿Cuál es la correcta?
gcc compilador (2)
Como un seguimiento interesante (aunque no de gran importancia práctica) a mi pregunta anterior: ¿Por qué C ++ nos permite rodear el nombre de la variable entre paréntesis al declarar una variable?
Descubrí que combinar la declaración entre paréntesis con la función de nombre de clase inyectado puede dar resultados sorprendentes con respecto al comportamiento del compilador.
Echa un vistazo al siguiente programa:
#include <iostream>
struct B
{
};
struct C
{
C (){ std::cout << "C" << ''/n''; }
C (B *) { std::cout << "C (B *)" << ''/n'';}
};
B *y = nullptr;
int main()
{
C::C (y);
}
-
Compilar con g ++ 4.9.2 me da el siguiente error de compilación:
main.cpp:16:10: error: cannot call constructor ''C::C'' directly [-fpermissive]
-
Se compila correctamente con MSVC2013 / 2015 e imprime
C (B *)
-
Se compila con éxito con clang 3.5 e imprime
C
Entonces, la pregunta obligatoria es ¿cuál es la correcta? :)
(Sin embargo, me incliné fuertemente hacia la versión clang y la forma msvc de dejar de declarar variables después de solo cambiar el tipo con técnicamente su typedef parece un poco extraño)
G ++ es correcto ya que da un error.
Debido a que el constructor no podría ser llamado directamente en dicho formato sin un
new
operador.
Y aunque su código llama
C::C
, parece una llamada de constructor.
Sin embargo, de acuerdo con el estándar C ++ 11 3.4.3.1, esta no es una llamada de función legal, o un nombre de tipo (
vea la respuesta de Mike Seymour
).
Clang está mal ya que ni siquiera llama a la función correcta.
MSVC es algo razonable, pero aún no sigue el estándar.
GCC es correcto, al menos de acuerdo con las reglas de búsqueda de C ++ 11. 3.4.3.1 [class.qual] / 2 especifica que, si el especificador de nombre anidado es el mismo que el nombre de la clase, se refiere al constructor, no al nombre de la clase inyectada. Da ejemplos:
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
Parece que MSVC lo malinterpreta como una expresión de conversión de estilo de función que crea una
C
temporal con
y
como parámetro constructor;
y Clang lo malinterpreta como una declaración de una variable llamada
y
de tipo
C