Ho alcune domande sul collegamento dalle seguenti variabili. Con esempi di 7.1.1/7 di C++ 03 e la sperimentazione di compilatori (Comeau, clang e GCC), sono venuto ai seguenti tipi di collegamento:Collegamento di varie variabili const/statiche
Prima
static
, quindiextern
static int a; // (a) extern int a; // (b) valid, 'a' still internal
Mi è chiaro secondo la sezione 3.5: (a) implica il collegamento interno. E (b) implica anche il collegamento interno, perché il nome "a" è dichiarato statico (da (a)).
primo
extern
, quindistatic
extern int b; // (c) static int b; // (d) invalid!
First, (c) implica linkage esterno. Ma (d) implica il collegamento interno perché il nome "b" è dichiarato statico con (d). Questo non è valido secondo 7.1.1/7, poiché il collegamento implicito non è coerente.
primo
const
, quindiextern
const double pi1 = 3.14; // (e) extern const double pi1; // (f) valid and 'pi1' is internal
First, (e) implica collegamento interno, perché è const, né dichiarato extern espressa o implicita precedentemente linkage esterno. E (f) dovrebbe implicare il collegamento extern ed essere un errore, perché dichiara esplicitamente il nome extern, ma i compilatori lo mantengono interno! Perché così?Questa è la mia domanda.
Prima
extern
, quindiconst
extern const double pi2; // (g) const double pi2 = 3.14; // (h) valid and 'pi2' is external
Ora, (g) implica collegamento esterno perché abbiamo esplicitamente dichiarato extern. E (h) implica anche il collegamento esterno perché (g) dichiarato esplicitamente extern.
ho sperimentalmente scoperto il collegamento per 3 e 4 con il seguente modello (il secondo argomento deve avere collegamento esterno)
template<typename T, T&> struct ensure { };
ensure<const double, pi1> e1; // failed
ensure<const double, pi2> e2; // succeeded
Sommario: La discussione con Charles Bailey si è rivelata abbastanza fruttuosa e ha mostrato che ci sono due possibili interpretazioni di 3.5/3
, dove l'importa letture nt punto elenco
Un nome con ambito namespace (3.3.5) presenta il collegamento interno se è il nome di
- un oggetto o riferimento che viene dichiarata esplicitamente const e extern né esplicitamente né dichiarato precedentemente dichiarati in collegamento esterno;
Se guardiamo al punto (f)
, quindi le due interpretazioni arrivano a conclusioni diverse, come illustrato di seguito
La prima interpretazione osserva che
pi1
è dichiaratoconst
ma è anche dichiarataextern
. La variabile ha quindi il collegamento esterno.La seconda interpretazione interpreta entrambe le occorrenze di "dichiarato" per fare riferimento alla stessa dichiarazione. In questo modo, significa che è dichiarato
const
, ma nonextern const
. Notiamo che(e)
è dichiaratoconst
e nonextern const
, pertanto viene fornito il collegamento internopi1
.
Ora, quale interpretazione è corretta? Non riesco a determinare da quella dicitura, ma i compilatori sembrano interpretare questo secondo modo. In particolare, se prendiamo la prima interpretazione, l'ultima parte citata di 3.5/3
sarebbe superflua, perché non ci sarebbe uno scenario valido in cui un nome sarebbe dichiarato const
e dichiarato in precedenza con linkage esterno ma senza un esplicito extern
.
Forse mi manca qualcosa, ma 3 non è uguale a 1? (Cioè, il nome 'pi1' è 'dichiarato statico' per così dire?). Anche se suppongo di aver semplicemente pregato perché 4 non sia valido. – GManNickG
@GMan, vedi 3.5/3 per questi due casi. Sono gestiti da diversi punti elenco. –
@GMan per 4, il primo lo rende esterno e il secondo non lo rende interno, perché il nome è stato dichiarato esplicitamente esterno (dalla prima dichiarazione). Quindi, sia solo il primo, sia il primo e il secondo insieme implicano lo stesso collegamento. Per 2, solo il primo implica il collegamento esterno, ma il primo e il secondo insieme implicano il collegamento interno perché il nome è esplicitamente dichiarato statico dal secondo. Quindi non è valido. –