2015-07-27 13 views
6

Mentre il nome di una struttura deve essere univoco nell'insieme di strutture all'interno di un namespace, tale nome può essere "condiviso" con variabili e funzioni. Ad esempio, il seguente codice viene compilato bene:univocità dei nomi di struttura

// Code 1 
struct h{}; 
int h{ 8 }; 

Allo stesso modo, non v'è alcuna collisione in:

// Code 2 
struct h{}; 
void h(){} 

1) Qual è stato il ragionamento di permettere che la condivisione nome?

Inoltre, se inseriamo modelli nel mix, abbiamo alcune situazioni strane. Il codice

// Code 3 
template< class H > void h(){} 
struct h{}; 
template< class H > struct j{}; 
void j(){} 

compilare; ma il seguente codice non riesce:

// Code 4 
struct h{}; 
template< class H > void h(){} 
void j(){} 
template< class H > struct j{}; 

2) Perché il ragionamento che ha permesso il codice 2 non era abbastanza buono per permettere codice a 4? Non sto chiedendo le regole nello standard. Sto chiedendo il motivo dietro a quelle regole.

+1

1) Compatibilità con C, dove dovresti usare 'struct h' per fare riferimento alla struct. Le intestazioni Unix ('stat.h') lo usano, quindi dovevano essere supportate anche in C++ e non potevano essere rimosse (fonte: D & E 2.8.2). – dyp

+0

Che cos'è D & E 2.8.2? – Hector

+0

["The Design and Evolution of C++"] (http://stroustrup.com/dne.html), di Bjarne Stroustrup. – dyp

risposta

3

1) Qual è stato il ragionamento per consentire la condivisione del nome?

Secondo "The Design and Evolution of C++", by Bjarne Stroustrup, sezione 2.8.2 "variabili di struttura vs. tipo Names", questa funzione è stata introdotta per mantenere la compatibilità con il linguaggio C. La C richiede l'uso della parola chiave struct per citarne una struttura (no parola chiave è necessaria per nominare un typedef). È quindi possibile utilizzare lo stesso identificatore di dichiarare una struttura e sia una funzione o una variabile:

struct X { int m; }; 
void X(void); 

X(); // call X 
struct X x; // create a new object of type X 

Una notevole semplificazione sintattica a beneficio degli utenti è stato introdotto in C++ a costo di qualche lavoro extra per implementatori e alcuni problemi di compatibilità C. [...] Nel contesto di C con Classi [dyp: il predecessore di C++], questo mi dava fastidio per qualche tempo perché rendeva sintatticamente i tipi di seconda classe cittadini di seconda classe.

[...]

La vera necessità di affrontare questo particolare problema deriva dal fatto che alcuni file di intestazione UNIX standard, in particolare, stat.h, si basano su un struct e una variabile o una funzione con lo stesso nome.

-D & E 2.8.2


2) Perché il ragionamento che ha permesso il codice 2 non era abbastanza buono per permettere codice a 4?

io prima di citare il C++ 11 standard:

Un modello di classe non deve avere lo stesso nome di qualsiasi altro modello, di classe, la funzione, variabile, l'enumerazione, enumeratore, namespace o digitare nello stesso ambito (3.3), ad eccezione di quanto specificato in (14.5.5 [dyp: class template specialization parziale]). Tranne quello un modello di funzione può essere sovraccaricato o da (non-modello) funzioni con lo stesso nome o altri modelli di funzione con lo stesso stesso nome (14.8.3 [dyp: questo si riferisce a sovraccarico]), un modello il nome dichiarato nello spazio dei nomi o nell'ambito della classe deve essere univoco in questo ambito.

-C++ 11 standard internazionale [Temp] p5

Secondo la mia interpretazione di questo passo, i codici 3 e 4 sono entrambi illegali. clang ++ li respinge, ma accetta la prima parte del codice 3:

template< class H > void h(){} 
struct h{}; 

che, secondo [temperatura] p5, dovrebbe essere illegale pure.

Considerando illegali tutti questi esempi (3, 4 e l'inizio di 3), penso che la motivazione sia che in questi casi non è necessaria l'eccezione di compatibilità: C non ha modelli.