Argomento predefinito nel mezzo dell’elenco dei parametri?

Ho visto una dichiarazione di funzione nel nostro codice che appariva come segue

void error(char const *msg, bool showKind = true, bool exit); 

Ho pensato innanzitutto che si tratta di un errore perché non è ansible avere argomenti predefiniti nel mezzo delle funzioni, ma il compilatore ha accettato questa dichiarazione. Qualcuno ha visto questo prima? Sto usando GCC4.5. È un’estensione GCC?

La cosa strana è che se lo faccio in un file separato e provo a compilare, GCC lo rifiuta. Ho ricontrollato tutto, incluse le opzioni del compilatore utilizzate.

Quel codice funzionerebbe se nella prima dichiarazione della funzione, l’ultimo parametro ha un valore predefinito, qualcosa del genere:

 //declaration void error(char const *msg, bool showKind, bool exit = false); 

E poi nello stesso ambito puoi fornire valori predefiniti per altri argomenti (dal lato destro), nella dichiarazione successiva, come:

 void error(char const *msg, bool showKind = true, bool exit); //okay //void error(char const *msg = 0 , bool showKind, bool exit); // error 

che può essere definito come:

 error("some error messsage"); error("some error messsage", false); error("some error messsage", false, true); 

Demo online: http://ideone.com/aFpUn

Nota se fornisci il valore predefinito per il primo parametro (da sinistra), senza fornire il valore predefinito per il secondo, non verrà compilato (come previsto): http://ideone.com/5hj46


§8.3.6 / 4 dice

Per le funzioni non modello, gli argomenti predefiniti possono essere aggiunti nelle dichiarazioni successive di una funzione nello stesso ambito.

Esempio dallo standard stesso:

 void f(int, int); void f(int, int = 7); 

La seconda dichiarazione aggiunge il valore predefinito!

Vedi anche §8.3.6 / 6.

La risposta potrebbe essere in 8.3.6:

8.3.6 Argomenti predefiniti

6 Ad eccezione delle funzioni membro dei modelli di class, gli argomenti predefiniti in una definizione di funzione membro che appare al di fuori della definizione della class vengono aggiunti all’insieme di argomenti predefiniti forniti dalla dichiarazione della funzione membro nella definizione della class. Gli argomenti predefiniti per una funzione membro di un modello di class devono essere specificati nella dichiarazione iniziale della funzione membro all’interno del modello di class.

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 

Dopo aver letto questo, ho scoperto che MSVC10 ha accettato quanto segue con le estensioni del compilatore distriggerste:

 void error(char const* msg, bool showKind, bool exit = false); void error(char const* msg, bool showKind = false, bool exit) { msg; showKind; exit; } int main() { error("hello"); }