2015-06-23 8 views
10

Chiedo a me stesso perché il seguente codice funziona e ciò che l'identificatore extern fa quando si crea un'istanza baz_instance:Passare una struttura a un modello con extern const. A cosa serve l'extern?

struct baz { 
    int value; 
}; 

extern const baz baz_instance = {3}; 

template<baz const& b> 
int foo(){ 
    return b.value; 
} 

int main(){ 
    foo<baz_instance>(); 
    return 1; 
} 

Perché il codice di cui sopra compilare in primo luogo, e perché non si compila più se il extern specificatore è lasciato fuori? Che cosa fa lo specificatore extern in questo esempio?

risposta

6

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.

0

La parola chiave extern indica che la variabile è stata definita in un'altra unità di compilazione (file di origine).

Quindi nel tuo caso, bazdovrebbe essere definiti in un file di origine diversa e extern è un modo di dire questa è una variabile non è definita in questo file sorgente, ma in una diversa, e troverete durante compilazione.

La parola chiave extern significa "dichiarazione senza definizione". In altre parole, è un modo per dichiarare esplicitamente una variabile o forzare una dichiarazione senza una definizione.

+0

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

+0

Vedere la modifica nella mia risposta –

1

Da 14.3.2.1 gli stati standard:

Un modello-argomento per un non-tipo, non-template-parametro deve essere uno dei seguenti:

  • l'indirizzo di un oggetto o funzione con il collegamento esterno , inclusi i modelli di funzione e gli id ​​di modello di funzione ma esclusi i membri di classe non statici , espressi come & id-expression in cui è disponibile l'opzione & l se il nome si riferisce a una funzione o array o se il parametro di modello corrispondente è un riferimento;

Da https://stackoverflow.com/a/643927/451600 da mweerden

1

Il extern parola significa che avrà linkage esterno, in altre parole sarà esportata simbolo quando l'unità di traduzione viene compilato. Poiché il tuo tipo è const, per impostazione predefinita ha un collegamento interno (come se fosse stato dichiarato static). I modelli non possono dipendere da tipi che hanno solo il collegamento interno.

Mi piacerebbe sapere il motivo, ma sembra che sia stato perso per le sabbie del tempo: Why did C++03 require template parameters to have external linkage?.