2010-03-19 1 views
8

Perché il seguente dare alcun errore di compilazione ?:Nessuna "ridefinizione dell'errore di parametro predefinito" per la funzione membro modello di classe?

// 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 
} 

Sembra come se il è solo silenziosamente ignorato dal compilatore. Perchè è questo?
La cosa interessante è che se la definizione del modello di classe è in Main.cpp anziché un file di intestazione, effettivamente ottengo il parametro predefinito ridefinizione errore.

Ora so che il compilatore si lamenterà di questo se fosse solo una funzione ordinaria (non di modello).

Che cosa dice lo standard sui parametri predefiniti nelle funzioni membro modello di classe o nei modelli funzione?

+1

g ++ * fa * interrompe la compilazione con un errore. – sth

+0

Quando si dice "... se la dichiarazione del modello è in ..." Suppongo si intenda la definizione del modello di classe, ad esempio "modello classe x {....};'. In tal caso, stai dicendo che sostituire la direttiva include con questa definizione di classe modello produce un messaggio del compilatore diverso? Ciò suggerisce che c'è qualcos'altro nel file di intestazione, cioè provare a copiare l'intero contenuto del file di intestazione nel punto in cui era presente la direttiva di inclusione e presumibilmente non si riceve alcun avvertimento sul compilatore? – Troubadour

+0

Potrebbe essere correlato in qualche modo a questo errore VC++: https://connect.microsoft.com/VisualStudio/feedback/details/496593/msdn-forum-splitting-templated-function-with-default-argument-into-declaration-definition -gives-compilation-error –

risposta

3

8.3.6 §6 Gli argomenti standard in una definizione di funzione membro che appare fuori della definizione della classe vengono aggiunti al set di argomenti di default forniti dalla dichiarazione funzione membro della classe definizione.
[Esempio:

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 esempio]

Secondo lo standard, si dovrebbe dare un errore.

+3

@tusbar stai citando solo parte di quel paragrafo. Dice all'inizio "Ad eccezione delle funzioni membro dei modelli di classe, ...". –

+4

Interessante: C++ 03 differisce da C++ 98. Quello che @tusbar ha citato è il testo C++ 98, mentre C++ 03 ha aggiunto l'eccezione per i modelli di classe e aggiunto al paragrafo "Gli argomenti predefiniti per una funzione membro di un modello di classe devono essere specificati nella dichiarazione iniziale della funzione membro all'interno del modello di classe. " - sospetto che questo sia inteso a vietare gli argomenti predefiniti nelle definizioni fuori classe nel caso di membri di modelli di classe dicendo che tutti gli argomenti predefiniti devono essere specificati in classe [invece che all'esterno della classe] tuttavia a me sembra non chiaro (vieta i duplicati?). –

+1

Ho esaminato http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html # 217 e sembra che l'intenzione sia quella di vietare qualsiasi allineamento predefinito fuori classe per i membri del modello. Inoltre, penso ora poiché l'argomento predefinito fuori dalla classe è considerato distinto da quello in classe, anche se in modo lessicalmente identico, viola il vincolo "deve essere specificato nella dichiarazione iniziale". Quindi questo ha senso se si ottiene un errore in fase di compilazione. Il "numero 3.13" a cui si riferisce John Spicer può essere letto in questo documento: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1995/N0607.pdf –