#Pragma fa parte dello standard C ++ 11?


140

Tradizionalmente, il modo standard e portatile per evitare inclusioni multiple di intestazione in C ++ era / è quello di utilizzare lo #ifndef - #define - #endifschema di direttive pre-compilatore chiamato anche schema di macro-guardia (vedi frammento di codice sotto).

#ifndef MY_HEADER_HPP
#define MY_HEADER_HPP
...
#endif

Nella maggior parte delle implementazioni / compilatori (vedi immagine sotto), tuttavia, esiste un'alternativa più "elegante" che ha lo stesso scopo dello schema di macro-guardia chiamato #pragma once. #pragma oncepresenta diversi vantaggi rispetto allo schema di macro-guardia, incluso meno codice, elusione degli scontri con i nomi e talvolta miglioramento della velocità di compilazione.

inserisci qui la descrizione dell'immagine

Facendo delle ricerche, mi sono reso conto che sebbene la #pragma oncedirettiva sia supportata da quasi tutti i compilatori conosciuti, c'è una torbidità sul fatto che la #pragma oncedirettiva faccia parte o meno dello standard C ++ 11.

Domande:

  • Qualcuno potrebbe chiarire se la #pragma oncedirettiva fa parte o meno dello standard C ++ 11?
  • Se non fa parte dello standard C ++ 11, ci sono piani per includerlo nelle versioni successive (ad esempio, C ++ 14 o versioni successive)?
  • Sarebbe anche bello se qualcuno potesse approfondire ulteriormente i vantaggi / gli svantaggi nell'uso di una delle due tecniche (es. Macro-guardia contro #pragma once).

9
Per inciso, l'uso di caratteri di sottolineatura doppi per le protezioni delle testate è proibito dallo standard, che riserva all'implementazione tutti i simboli che iniziano con un doppio trattino basso (oltre ad altri).
Matteo Italia,

9
Anche l'uso di un carattere di sottolineatura iniziale seguito da una lettera maiuscola è vietato. Secondo, dov'è la torbidità? Vedo solo il supporto del compilatore, non vedo nessuno affermare che fa parte dello standard?
Yakk - Adam Nevraumont,

1
Per il terzo punto, guarda la domanda correlata: #pragma una volta è sicuro includere la guardia? Ha avuto una situazione in cui le protezioni per le testate funzionano ma di #pragma oncesolito no.
user1942027

1
possibile duplicato in quanto risponde a questa domanda senza menzionare C ++ 11.
Yakk - Adam Nevraumont,

3
Bene, non è codificato in nessun documento ufficiale, ma puoi considerarlo come standard di fatto .
Siyuan Ren,

Risposte:


107

#pragma oncenon è standard. È un'estensione diffusa (ma non universale), che può essere utilizzata

  • se i problemi di portabilità sono limitati e
  • puoi essere sicuro che tutti i tuoi file include siano sempre su un disco locale.

È stato considerato per la standardizzazione, ma rifiutato perché non può essere implementato in modo affidabile. (I problemi si verificano quando si dispone di file accessibili attraverso diversi supporti remoti diversi.)

È abbastanza facile garantire che non vi siano conflitti di guardia inclusi in un singolo sviluppo. Per le librerie, che possono essere utilizzate da molti sviluppi diversi, la soluzione ovvia è generare un sacco di caratteri casuali per la guardia di inclusione quando lo si crea. (Un buon editor può essere impostato per fare questo per te ogni volta che apri una nuova intestazione.) Ma anche senza questo, devo ancora incontrare problemi con conflitti tra librerie.


11
Non solo supporti remoti. Hardlink, softlink, costrutti subst (su Windows). Può diventare davvero disordinato.
Tonny,

45
Perché il compilatore non può usare i checksum SHA-1 o MD5 per identificare i file?
Sergey,

29
Non vedo davvero il punto di non mettere qualcosa nello standard se tutti i principali compilatori lo supportano. Ci sono cose in realtà nello standard molto meno supportate di così. Inoltre, sembra abbastanza sciocco lamentarsi dei problemi dei bordi, quando parliamo di file di inclusione, dove gli scontri con i nomi di file sono già un grosso problema. Sarebbe stato bello se questa richiesta di una funzionalità senza problemi al 100% fosse stata applicata al concetto di file di intestazione #incluso in generale.
TED

38
Se il tuo codice include alcuni file da posizioni diverse attraverso collegamenti simbolici o montaggi strani, non è già portatile. Pertanto, sostenere che pragma oncenon è possibile implementare in modo portabile qualcosa che è intrinsecamente non portatile (e che non dovrebbe nemmeno essere considerato) è ancora un'altra assurdità del mondo capovolto del C ++.
doc,

7
@JoseAntonioDuraOlmos Concordo sul fatto che i collegamenti simbolici sono una funzionalità del sistema operativo, che non rientra nell'ambito del linguaggio C ++. Da qui sorge la domanda sul perché il comitato C ++ dovrebbe prendere in considerazione qualcosa che esula dal campo di applicazione del linguaggio? Cercare di garantire qualcosa che non è la loro responsabilità non ha alcun senso IMO. DOS ha supportato solo 8 + 3 caratteri per nome file, ma nessuno ha sostenuto che #includedebba essere rimosso, perché si può fare un uso improprio della direttiva. #pragma oncenon limita in alcun modo la portabilità, a condizione che non si sfruttino i collegamenti simbolici per interrompere la compilazione.
doc

32

La sezione §16.6 della norma ( bozza N3936 ) descrive le #pragmadirettive come:

Una direttiva di preelaborazione del modulo

# pragma pp-tokensopt new-line

fa sì che l'implementazione si comporti in un modo definito dall'implementazione. Il comportamento potrebbe causare errori nella traduzione o comportare comportamenti non conformi del traduttore o del programma risultante. Qualsiasi pragma non riconosciuto dall'implementazione viene ignorato.

Fondamentalmente #pragma onceè un'istanza specifica dell'implementazione di una #pragmadirettiva e no, non è standard. Ancora.

Spesso è ampiamente supportato dalla maggior parte dei "principali compilatori" tra cui GCC e Clang ed è quindi talvolta raccomandato di evitare la piastra di protezione delle guardie di inclusione.


10
Si noti che è possibile sia #pragmae #defineheader-guardia.
Yakk - Adam Nevraumont,

18
"Qualsiasi pragma non riconosciuto dall'implementazione viene ignorato" . Significa che il messaggio: Attenzione: la direttiva pragma non riconosciuta non è conforme?
rodrigo,

6
"ed è quindi il modo raccomandato per evitare la piastra di protezione delle inclusioni" - una dichiarazione molto audace. È un modo non standard e i vantaggi di usarlo sono pochi e non sono stati rilevanti nella mia esperienza, quindi ho dovuto portare via il mio +1.
Alex,

19
@Yakk: se qualcuno scrive un #defineheader-guard, non ha NESSUN motivo per scrivere #pragma once.
Nawaz,

5
@Nawaz Un compilatore può conservare una cache di ogni file (per percorso) che è stato #pragma onced, e nel caso in cui sia di #includenuovo d può saltare il #include(nemmeno aprire il file). gcc fa lo stesso con le protezioni delle testate, ma è molto, molto fragile. L' #pragmauno è facile da fare, la guardia di intestazione uno è difficile.
Yakk - Adam Nevraumont,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.