2015-12-22 8 views
12

Ho appena scoperto che il seguente codice non è una valida C++ (che non analizza in int dopo ~):È legale chiamare un distruttore su int32_t?

int x = 5; 
x.~int(); 

Tuttavia, il seguente frammento funziona:

int32_t x = 5; 
x.~int32_t(); 

Questo perché int32_t è un typedef nella mia particolare implementazione di C++ e un distruttore può, apparentemente, essere chiamato su qualsiasi tipo typedef'ed.

La mia domanda è: è necessaria un'implementazione di C++ per consentire la compilazione del secondo frammento? In particolare, è int32_t garantito come typedef, ed è il compilatore necessario per consentire la distruzione di un typedef se sa che typedef typedef qualcosa a int?

+0

Sì. 'int32_t' non è un tipo built-in e non può essere una macro. –

+0

@ Cheersandhth.-Alf La bozza standard di C++ 14 afferma 'typedef signed intere type int32_t;' come la definizione di 'int32_t'. Per quanto posso dire, questo non lascia molto spazio per i tipi definiti dall'utente e tutti o anche una macro. – Downvoter

+0

Per evitare una domanda vicina/aprire una guerra di domande, non ho intenzione di votare per chiudere come duplicato, MA ... questo è un duplicato della domanda collegata. Solo perché quell'altra domanda non menziona 'int32_t' non significa che quell'altra domanda non risponda alle tue. –

risposta

8

C'è un chiaro requisito che int32_t sia un typedef. Iniziamo con [cstdint.syn]/2:

L'intestazione definisce tutte le funzioni, i tipi e i macro lo stesso di 7.18 nello standard C.

Quindi da lì guardiamo il requisito per la libreria C:

Il typedef nome intN_t designa un tipo intero con segno con la larghezza N, nessun bit di imbottitura, e la rappresentazione complemento a due.

[enfasi aggiunta]

Quindi sì, int32_t deve essere un "typedef nome".

Anche se (per quanto ne so) non è mai dichiarato direttamente nel testo normativo, la seguente nota chiarisce che il richiamo di un distruttore per un typedef che si risolve in un tipo built-in è destinato alla compilazione e al successo ([class .dtor]/16):

Nota: la notazione per la chiamata esplicita di un distruttore può essere utilizzata per qualsiasi nome di tipo scalare (5.2.4). Consentire questo rende possibile scrivere codice senza dover sapere se esiste un distruttore per un dato tipo. Ad esempio,

typedef int I; 
I* p; 
p->I::~I(); 
+0

Lo snippet è ovviamente un comportamento non definito (accesso membro tramite un puntatore jolly).O lo Standard garantisce che l'uso di questa sintassi su una primitiva è un no-op e l'accesso ai membri non avviene mai realmente? –

+0

@ BenVoigt: buona domanda. Non penso che il puntatore debba essere effettivamente dereferenziato, ma non sono sicuro di poter trovare una dichiarazione per dirlo con certezza. –

+0

"L'unico effetto è la valutazione dell'espressione post fi x prima del punto o della freccia." (5.2.4) Quindi quindi '(* p) .I: ~ I()' male ma 'p-> I :: ~ I()' buono? E in realtà non importa quale sia il tipo? Sembra un difetto. –

Problemi correlati