Come determinare la versione dello standard C ++ utilizzato dal compilatore?


115

Come si determina quale versione dello standard C ++ è implementata dal compilatore? Per quanto ne so, di seguito sono riportati gli standard che ho conosciuto:

  • C ++ 03
  • C ++ 98

3
Hai etichettato questo c ++ , ma due dei tre standard che hai elencato non sono standard C ++. In quale lingua sei interessato?
Rob Kennedy,

1
E la domanda è stata posta solo un paio di minuti fa. ( stackoverflow.com/questions/7132440/… )
Mat

1
@Mat: Posato e chiuso perché la domanda era spazzatura e aveva altre sciocchezze arbitrarie su di essa. L'ho ripubblicato in una forma decente. Sarei felice di chiudere questo se sembra che l'originale verrà riparato e ripreso, ma non sto trattenendo il respiro.
Gare di leggerezza in orbita il

1
@ Mat: Beh, la risposta migliore non è un elenco statico di compilatori, ma un mezzo per determinare da soli cosa è in uso. Quindi eccoti.
Gare di leggerezza in orbita il

1
@Als: sarà presto. Lo prometto. Inoltre, il c++-faqtag non ha alcun pre-requisito effettivo "numero di volte richiesto" che devi superare; riguarda più il formato e la generalità della cosa.
Gare di leggerezza in orbita

Risposte:


13

Per quanto ne so, non esiste un modo globale per farlo. Se guardi le intestazioni delle librerie che supportano più piattaforme / compilatori multipli, troverai sempre molte definizioni che utilizzano costrutti specifici del compilatore per determinare tali cose:

/*Define Microsoft Visual C++ .NET (32-bit) compiler */
#if (defined(_M_IX86) && defined(_MSC_VER) && (_MSC_VER >= 1300)
     ...
#endif

/*Define Borland 5.0 C++ (16-bit) compiler */
#if defined(__BORLANDC__) && !defined(__WIN32__)
     ...
#endif

Probabilmente dovrai farlo tu stesso per tutti i compilatori che usi.


1
Non è la mia risposta attesa, ma immagino che non ci sia un modo universale per scoprirlo.
jasonline

248

Dalle domande frequenti su Bjarne Stroustrup C ++ 0x :

__cplusplus

In C ++ 0x la macro __cplusplusverrà impostata su un valore che differisce da (è maggiore di) l'attuale 199711L.

Anche se questo non è utile come si vorrebbe. gcc(apparentemente per quasi 10 anni) ha impostato questo valore 1, escludendo un compilatore principale, fino a quando non è stato risolto quando è uscito gcc 4.7.0 .

Questi sono gli standard C ++ e il valore che dovresti aspettarti in __cplusplus:

  • C ++ pre-C ++ 98: __cplusplusè 1.
  • C ++ 98: __cplusplusè 199711L.
  • C ++ 98 + TR1: si legge come C ++ 98 e non c'è modo di verificare che io sappia.
  • C ++ 11: __cplusplusè 201103L.
  • C ++ 14: __cplusplusè 201402L.
  • C ++ 17: __cplusplusè 201703L.

Se il compilatore potrebbe essere un vecchio gcc, dobbiamo ricorrere a hackery specifici del compilatore (guarda una macro di versione, confrontala con una tabella con funzionalità implementate) o usa Boost.Config (che fornisce le macro pertinenti ). Il vantaggio di ciò è che possiamo effettivamente scegliere funzionalità specifiche del nuovo standard e scrivere una soluzione alternativa se la funzionalità è mancante. Questo è spesso preferito a una soluzione all'ingrosso, poiché alcuni compilatori affermano di implementare C ++ 11, ma offrono solo un sottoinsieme delle funzionalità.

Il Wiki Stdcxx ospita una matrice completa per il supporto del compilatore delle funzionalità C ++ 0x (se hai il coraggio di verificare tu stesso le funzionalità).

Sfortunatamente, un controllo più finemente granulare delle funzionalità (ad esempio singole funzioni di libreria come std::copy_if) può essere fatto solo nel sistema di compilazione della tua applicazione (esegui il codice con la funzionalità, controlla se ha compilato e ha prodotto risultati corretti - autoconfè lo strumento di scelta se si prende questo percorso).


Non sembra che i fornitori di compilatori stiano aggiornando questo - forse stanno aspettando fino a quando non saranno completamente conformi allo standard? ( Stackoverflow.com/q/14131454/11698 )
Richard Corden

2
@prnr: potrebbe essere vero, ma spetta all'utente che ha posto la domanda decidere quale risposta accettare. Nel momento in cui è stata pubblicata la risposta attualmente contrassegnata come accettata, era corretta, quindi il poster originale l'ha accettata. Quell'utente potrebbe decidere di modificare la risposta accettata, ma potrebbe non essere più attivo sul sito. Vedi: meta.stackexchange.com/questions/120568/…
Dan Korn

3
vs2017 fornisce il valore di __cplusplus 199711
Al Mamun

5
@AlMamun Microsoft è stato parzialmente risolto __cplusplussolo in VS 15.7. Vedi il loro blog del team di Visual C ++
Ivan_Bereziuk

1
Il collegamento alla FAQ è interrotto.
Brainplot

38

Per favore, esegui il seguente codice per controllare la versione.

#include<iostream>

int main() {
    if (__cplusplus == 201703L) std::cout << "C++17\n";
    else if (__cplusplus == 201402L) std::cout << "C++14\n";
    else if (__cplusplus == 201103L) std::cout << "C++11\n";
    else if (__cplusplus == 199711L) std::cout << "C++98\n";
    else std::cout << "pre-standard C++\n";
}

8
È divertente, perché negli studi visivi il valore di __cplusplus è 199711L e il codice che hai pubblicato ha restituito c ++ 98, tuttavia, ho usato le funzionalità di c ++ 14 inclusi i modelli di variabili e decltype (auto). È possibile che sia stata implementata la versione sbagliata della macro?
Colin Hicks

2
Vedere: devblogs.microsoft.com/cppblog/… (TLDR: specificare il flag /Zc:__cplusplus)
Daan Timmer

@DaanTimmer Sono confuso da quell'articolo, sembra presumere la conoscenza di come usare la /Zc:__cplusplusbandiera. Non posso semplicemente std::cout << /Zc:__cplusplus;perché i due punti e le barre non possono essere parte dei nomi delle variabili ovviamente. Sei in grado di spiegare come farlo? Grazie.
A__


7

A seconda di ciò che vuoi ottenere, Boost.Config potrebbe aiutarti. Non fornisce il rilevamento della versione standard, ma fornisce macro che consentono di verificare il supporto di specifici linguaggi / funzionalità del compilatore.


3
Il controllo delle funzionalità è probabilmente un'idea migliore rispetto al controllo delle versioni standard, comunque. Pochi compilatori supportano tutto da uno standard, ma se tutti supportano il numero limitato di funzionalità di cui hai bisogno, allora non importa se il resto delle funzionalità di un dato standard sono implementate e funzionano correttamente.
Rob Kennedy,



0

Dopo un rapido google :

__STDC__e __STDC_VERSION__, vedi qui


Se __STDC__è definito e qual è il suo valore, sono definiti dall'implementazione in C ++.
Rob Kennedy,

@ Rob: Sì, lo è. @ Tor: ho provato in VC ++ 2005 ma dice che STDC è un identificatore non dichiarato. Tuttavia, è elencato come una di quelle macro predefinite. Tuttavia, STDC_VERSION non esiste.
jasonline

Questo ti dice la versione del linguaggio di programmazione C supportata dal compilatore. Non ti dice nulla sulla versione del linguaggio C ++ supportato.
Dan Moulding

0

Normalmente dovresti usare __cplusplusdefine per rilevare c ++ 17, ma per impostazione predefinita il compilatore microsoft non definisce quella macro correttamente, vedi https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ - hai bisogno per modificare le impostazioni del progetto per includere lo /Zc:__cplusplusswitch, oppure puoi usare la sintassi come questa:

#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
     //C++17 specific stuff here
#endif
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.