2015-06-16 13 views
6

Da un punto di vista pratico, capisco che sia typedef e test sono un po ' "superflui" e devono essere rimossi se vogliamo che il seguente codice per compilare:Perché i modelli typedef sono illegali?

template< typename type_t > 
typedef struct tagTest 
{ 
    int a; 
} test; 

Tuttavia, ho pensato che l'insieme di le dichiarazioni typedef erano un sottoinsieme dell'insieme di dichiarazioni. Si è appena verificato uno specifico identificatore decimale . Quello era il mio razionalizzazione

typedef struct tagTest 
{ 
    int a; 
} test; 

introducendo l'identificatore teste dichiarando la struttura tagTest. Se tale interpretazione è corretta, il paragrafo seguente dello standard dovrebbe consentire templatetypedef (anche se non con il significato fornito dalla parola chiave using).

La dichiarazione in un modello-dichiarazione sono - (1.1) dichiarare o definire una funzione, una classe o una variabile, o - (1.2) definire una funzione membro, una classe membro , un'enumerazione membro o un membro dati statico di una classe template o di una classe inserita all'interno di una classe template, o - (1.3) definiscono un modello membro di una classe template o una classe, o - (1,4) essere una dichiarazione alias.

Non riesco a vedere l'errore nel mio ragionamento, tuttavia la conclusione è illegale.

Quali sono le parti rilevanti dello standard che risolvono l'enigma sopra?


UPDATE Una parte del ragionamento di cui sopra utilizza il fatto che typedefstruct dichiara una struttura. L'identificatore typedef, per quanto ho capito, implica che tutte le variabili dichiarate siano realmente dei tipi. Vale a dire, lo typedef aggiorna test da una semplice variabile a un tipo che è equivalente allo tagTest dichiarato. Questo è il motivo per cui il seguente codice viene compilato (anche se con un avvertimento).

typedef struct tagTest 
{ 
    int a; 
}; 
tagTest t; 

Una delle risposte si occupa del superfluo test.Ma, è possibile usare typedef senza un dichiaratore because "Init-dichiaratore-list è facoltativo quando si dichiara una classe/struct/union di nome o di un nome di enumerazione"

+0

Er ... Nessuno di quei casi lo copre. Il fatto che la dichiarazione capiti di contenere qualcosa che dichiarerebbe una classe non significa che la dichiarazione stessa dichiari una classe. La dichiarazione definisce semplicemente un tipo. – hvd

+0

@hvd In C, un typedef che contiene una struttura taggata dichiara la struct e definisce un nome che lo alias. Stai dicendo che C++ è diverso in questo senso? – davmac

+0

@davmac No, siamo d'accordo sull'effetto finale di una tale dichiarazione. Sto dicendo che la parte che causa la dichiarazione della struttura non è la dichiarazione stessa, ma solo un sottocomponente di quella dichiarazione. E questo vale sia per C che per C++. – hvd

risposta

3

Template typedefs non potevano pre-C++ 11 e con C++ 11 template aliases sono stati introdotti per affrontare quei problemi. Cfr. C++ template typedefs e wikipedia.

Dal momento che, come avrete notato, lo standard non consente typedef di essere in là, il codice non è valido

alias dichiarazione:

using identifier attribute-specifier-seqopt= type-id ; 

typedef dichiarazioni non sono alias dichiarazioni.

Inoltre, non si può avere un dichiaratore se si sta dichiarando un modello di classe, è esplicitamente vietato dalla norma

[Temp]/p3

In un modello di dichiarazione , specializzazione esplicita o istanza esplicita l'elenco init-declarator nella dichiarazione deve contenere al massimo un dichiaratore. Quando una dichiarazione di questo tipo viene utilizzata per dichiarare un modello di classe, non è consentito alcun dichiaratore.

quindi nemmeno il seguente compilerà

template< typename type_t > 
struct tagTest 
{ 
    int a; 
} test; 

Edit:

Si nessuna parte precisa che

typedef struct S { }; 

dovrebbe essere un errore, così sia gcc e clang accettalo con un avvertimento. Presumo Clang conta su [Temp]/3 di emettere un errore nel caso in cui Typedef veniva usato con un modello, mentre gcc rifiuta questo codice immediatamente

template<typename T> 
typedef struct S { }; 

cfr. clang bug 22249

+0

Rimuovere il token 'test' ma mantenere lo specificatore' typedef' dovrebbe essere legale perché i dichiaranti sono facoltativi. – Hector

+0

@Hector ha modificato la domanda per aggiungere dettagli per quel caso –

+0

+1 Quel link su clang è bello. Ma per quanto riguarda il tuo paragrafo di apertura, non sostengo che 'template typedef struct S {};' dovrebbe funzionare allo stesso modo della parola chiave 'using'. Suppongo che lo standard consenta che sia legale con lo stesso significato di 'template struct S {};'. – Hector

1

Indipendentemente da ciò che la typedef definisce, cioè una dichiarazione typedef , che non è elencato in quei casi:

  • funzione [membro]
  • [membro] classe
  • variabile
  • membro censimento
  • membro di dati static di una classe template/di una classe nidificato all'interno di un modello di classe
  • template
  • membro di un modello di classe o di classe
  • dichiarazione alias

E tanto per essere chiari typedef dichiarazioni non sono alias dichiarazioni. Alias ​​dichiarazione, come specificato dalla grammatica al § 7 della norma sono:

alias dichiarazione:

using identifier attribute-specifier-seqopt= type-id ;

Senza contare che, se questo è stato possibile, quindi la dichiarazione modello using non sarebbe così "fredda" come lo sono oggi, e there would be little to no sense to have both.

+0

Penso che il punto OP sia che il testo non dice che la dichiarazione deve _be_ una dichiarazione "[membro] classe" (tra gli altri tipi), ma che "dichiarerà o definirà" una classe, che è un typedef con una struct la sottodichiarazione è discutibile. – davmac

1

C non supporta i modelli e la sintassi

typedef struct tagX { 
} X; 

in C++ è vestigiale C, lì per consentire un sostegno costante per C intestazioni ecc, non per l'uso in effettivo C++.

La sintassi C++ per quanto sopra è

struct X {}; 

(YMMV sul collocamento brace)

Problemi correlati