c++ - argumento por defecto, gcc vs clang
llvm 3.7 0 (3)
El código parece:
struct Foo {
Foo(const char *);
};
Foo::Foo(const char *str = 0)
{
}
VS 2013 y gcc 4.8.0 aceptan dicho código, mientras que el código 3.3 rechaza dicho código con:
error: la adición del argumento predeterminado en la redeclaración convierte a este constructor en un constructor predeterminado
¿Quién tiene razón desde el punto de vista estándar (C ++ 03 y C ++ 11)?
Nota:
También me gusta la elección de clang, pero voy a informar de errores a gcc y visual studio, y si esto no es correcto desde el punto de vista estándar, esto ayuda a convencer a los desarrolladores de compiladores para solucionar este problema.
GCC
Describí el problema aquí: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58194
Pero sin suerte, suspenden la corrección de errores hasta que el tiro se convierte en estándar.
Esto se ha discutido en la lista de correo de Clang y se ha enviado como un problema principal de informe de defectos 1344.
De la discusión de la lista de correo:
La idea es que la presencia de ciertos miembros especiales afecta las propiedades principales de un tipo de clase, como si es POD o se puede copiar de forma trivial. La decisión de estas propiedades no debe requerir el conocimiento del programa completo; Es importante para nosotros poder deducirlos solo a partir de la definición de clase. El caso realmente problemático es convertir un constructor "normal" en un constructor de copia o movimiento agregando argumentos predeterminados, pero la introducción de un constructor predeterminado por parte de IIRC también fue problemática.
La solución es que debe colocar el argumento predeterminado en la declaración inicial del constructor.
Esto fue discutido por última vez por WG21 en la reunión de Bloomington. Notas desde allí:
"Consenso: haga esto mal formado como se sugiere en la reseña. Cuestión básica 1344. Prioridad 0, Doug redacción".
Así que CWG ha acordado (en principio) que esto debe estar mal formado.
TL; DR Clang tiene razón cuando el defecto se soluciona (no estoy seguro si eso solo puede ocurrir oficialmente con C ++ 14, o si esas decisiones del Comité también pueden hacerse de manera retroactiva en C ++ 11)
Tienes una declaración y una definición. En su declaración no tiene un valor predeterminado, mientras que en su definición tiene un valor predeterminado. De hecho, la firma de la declaración es muy similar a la firma de la definición, pero no es la misma. Creo que el rigor es una buena idea, así que creo que es mejor hacer cumplir que la declaración es la misma que la definición.
Yo diría que CLANG tiene razón. El estándar dice (12.1.5 para las versiones anteriores y nuevas del estándar):
Un constructor predeterminado para una clase X es un constructor de clase X al que se puede llamar sin un argumento
Agregar el valor predeterminado al único argumento del constructor definitivamente hace posible llamarlo sin argumentos, por lo que es uno predeterminado. Además, 8.3.6 dice (énfasis mío):
Una expresión de argumento por defecto se especificará solo en la cláusula-declaración-parámetro de una declaración de función <...>