Questa è una delle parti dello standard che è passata da C++ 03 a C++ 11.
In C++ 03, [temp.arg.nontype] si legge:
Un modello-argomento per un non-tipo, non-template-parametro deve essere uno dei seguenti:
- [...]
- [...]
- l'indirizzo di un oggetto o una funzione con collegamento esterno, inclusi i modelli funzione e funzione template-ids ma esclusi i membri della classe non statici, espressa come & id-espressione dove il & è opzionale se il nome si riferisce ad un funzione o array, o se il parametro template corrispondente è un riferimento; o
- [...]
In C++ 11, che ha ottenuto aggiornato a seguito di issue 1155, anche se GCC ha ancora a bug per quanto riguarda questo comportamento:
- un'espressione costante (5.19) che indica l'indirizzo di un oggetto completo con durata di memorizzazione statica e collegamento esterno o interno o una funzione con collegamento esterno o interno , compresi i modelli di funzione e esclusi i membri di classe non statici, espresso (ignorando parentesi) come & espressione-ID, dove l'espressione-id è il nome di un oggetto o funzione, ad eccezione del fatto che lo & essere omesso se il nome si riferisce a una funzione o array e deve essere omesso se il corrispondente parametro modello è un riferimento; o
In C++ 14, che viene però ulteriore semplicità e non menziona neppure linkage.
Come per la tua domanda specifica, l'identificatore extern
aggiunge il collegamento esterno a baz_instance
. Senza di esso, baz_instance
ha un collegamento interno. In C++ 03, era necessario il collegamento esterno per avere un parametro di modello non di tipo di riferimento. In C++ 11, non lo fai più - quindi extern
non è più necessario e compila bene senza di esso.
Come si può vedere dal codice sorgente, baz non è stato definito in un altro file sorgente. Inoltre, non spiegherebbe perché l'istanza della struct può essere passata a un template con external, ma non può senza external. – smoes
Vedere la modifica nella mia risposta –