2010-03-19 5 views
8

¿Por qué no dar el siguiente error de compilación ?:¿No hay "redefinición de error de parámetro predeterminado" para la función de miembro de plantilla de clase?

// T.h 

template<class T> class X 
{ 
public: 
    void foo(int a = 42); 
}; 

// Main.cpp 

#include "T.h" 
#include <iostream> 

template<class T> void X<T>::foo(int a = 13) 
{ 
    std::cout << a << std::endl; 
} 

int main() 
{ 
    X<int> x; 
    x.foo(); // prints 42 
} 

Parece como si el se acaba en silencio ignorado por el compilador. ¿Por qué es esto?
Lo bueno es que si la definición de plantilla de clase está en Main.cpp en lugar de un archivo de cabecera, de hecho obtengo el error de redefinición del parámetro error.

Ahora sé que el compilador se quejará de esto si fuera una función normal (sin plantilla).

¿Qué dice el estándar sobre los parámetros predeterminados en las funciones de los miembros de la plantilla de clase o en las plantillas de funciones?

+1

g ++ * does * cancela la compilación con un error. – sth

+0

Cuando dices "... si la declaración de la plantilla está en ...", supongo que te refieres a la definición de la plantilla de clase, es decir, 'plantilla clase x {....};'. Si es así, ¿está diciendo que reemplazar la directiva de inclusión con esta definición de clase de plantilla produce un mensaje de compilador diferente? Eso sugiere que hay algo más en el archivo de encabezado, es decir, intente copiar todo el contenido del archivo de encabezado en donde estaba la directiva de inclusión y, presumiblemente, ¿entonces no recibe ninguna advertencia del compilador? – Troubadour

+0

Podría estar relacionado de alguna manera con este error de VC++: https://connect.microsoft.com/VisualStudio/feedback/details/496593/msdn-forum-splitting-templated-function-with-default-argument-into-declaration-definition -gives-compilation-error –

Respuesta

3

8.3.6 § 6 Los argumentos por defecto en una definición de función miembro que aparece fuera de la definición de clase se añaden al conjunto de argumentos predeterminados proporcionados por la declaración de función miembro de la clase definición.
[Ejemplo:

class C { 
    void f(int i = 3); 
    void g(int i, int j = 99); 
}; 
void C::f(int i = 3) // error: default argument already 
{ }     // specified in class scope 
void C::g(int i = 88, int j) // in this translation unit, 
{ }       // C::g can be called with no argument 

--end ejemplo]

De acuerdo con la norma, debe darle un error.

+3

@tusbar citan solo una parte de ese párrafo. Dice al principio "Excepto las funciones de miembros de las plantillas de clases, ...". –

+4

Interesante: C++ 03 difiere de C++ 98. Lo que @tusbar citado es el texto de C++ 98, mientras que C++ 03 agregó la excepción para las plantillas de clase y se agregó al párrafo "Los argumentos predeterminados para una función miembro de una plantilla de clase se especificarán en la declaración inicial de la función miembro dentro de la plantilla de la clase ". - Sospecho que esto está destinado a prohibir los argumentos predeterminados en las definiciones fuera de clase en el caso de los miembros de las plantillas de clase diciendo que los argumentos predeterminados se especificarán en clase [en lugar de fuera de la clase] sin embargo, a mí me parece no está claro (¿prohíbe los duplicados?). –

+1

Miré en http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html # 217 y parece que la intención es prohibir cualquier armadura predeterminada fuera de clase para los miembros de la plantilla. Además, creo que ahora que el argumento predeterminado fuera de clase se considera distinto del de la clase, incluso si es léxicamente idéntico, viola la restricción "se especificará en la declaración inicial". Entonces esto tiene sentido si obtienes un error de tiempo de compilación. El "número 3.13" al que se refiere John Spicer se puede leer en este documento: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1995/N0607.pdf –

Cuestiones relacionadas