Comment déterminer la version du standard C ++ utilisée par le compilateur?

115

Comment déterminez-vous quelle version du standard C ++ est implémentée par votre compilateur? Pour autant que je sache, voici les normes que j'ai connues:

  • C ++ 03
  • C ++ 98
Jasonline
la source
3
Vous avez marqué ce c ++ , mais deux des trois normes que vous avez répertoriées ne sont pas des normes C ++. Quelle (s) langue (s) vous intéresse (s)?
Rob Kennedy
1
Et la question a été posée il y a à peine quelques minutes. ( stackoverflow.com/questions/7132440/… )
Mat
1
@Mat: Posée et fermée parce que la question était insensée et contenait d'autres absurdités arbitraires. Je l'ai republié sous une forme décente. Je serais heureux de fermer celui-ci s'il semble que l'original sera réparé et rétabli, mais je ne retiens pas mon souffle.
Courses de légèreté en orbite
1
@Mat: Eh bien, la meilleure réponse n'est pas une liste statique de compilateurs, mais un moyen de déterminer par vous-même ce qui est utilisé. Alors voilà.
Courses de légèreté en orbite
1
@Als: Ce sera bientôt. Je promets. En outre, la c++-faqbalise n'a pas de pré-requis réel "nombre de fois demandé" que vous devez passer; il s'agit plus du format et de la généralité de la chose.
Courses de légèreté en orbite

Réponses:

13

À ma connaissance, il n'y a pas de moyen global de le faire. Si vous regardez les en-têtes des bibliothèques supportant plusieurs plates-formes / compilateurs multiples, vous trouverez toujours de nombreux définitions qui utilisent des constructions spécifiques au compilateur pour déterminer ces choses:

/*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

Vous devrez probablement faire de telles définitions vous-même pour tous les compilateurs que vous utilisez.

ADAIR SOUPLE ROUGE
la source
1
Ce n'est pas ma réponse attendue, mais je suppose qu'il n'y a tout simplement pas de moyen universel de le découvrir.
jasonline
248

À partir de la FAQ Bjarne Stroustrup C ++ 0x :

__cplusplus

En C ++ 0x, la macro __cplusplussera définie sur une valeur différente de (supérieure à) la valeur actuelle 199711L.

Bien que ce ne soit pas aussi utile qu'on le souhaiterait. gcc(apparemment pendant près de 10 ans) avait cette valeur fixée à 1, excluant un compilateur majeur, jusqu'à ce qu'elle soit corrigée lorsque gcc 4.7.0 est sorti .

Voici les normes C ++ et la valeur à laquelle vous devriez pouvoir vous attendre __cplusplus:

  • C ++ pré-C ++ 98: __cplusplusest 1.
  • C ++ 98: __cplusplusest 199711L.
  • C ++ 98 + TR1: Cela se lit comme C ++ 98 et il n'y a aucun moyen de vérifier que je sache.
  • C ++ 11: __cplusplusest 201103L.
  • C ++ 14: __cplusplusest 201402L.
  • C ++ 17: __cplusplusest 201703L.

Si le compilateur est plus ancien gcc, nous devons recourir au piratage spécifique au compilateur (regardez une macro de version, comparez-la à une table avec des fonctionnalités implémentées) ou utilisez Boost.Config (qui fournit des macros pertinentes ). L'avantage de ceci est que nous pouvons en fait choisir des fonctionnalités spécifiques de la nouvelle norme et écrire une solution de contournement si la fonctionnalité est manquante. Ceci est souvent préféré à une solution de gros, car certains compilateurs prétendront implémenter C ++ 11, mais n'offriront qu'un sous-ensemble des fonctionnalités.

Le Wiki Stdcxx héberge une matrice complète pour la prise en charge par le compilateur des fonctionnalités C ++ 0x (si vous osez vérifier les fonctionnalités vous-même).

Malheureusement, une vérification plus fine des fonctionnalités (par exemple des fonctions de bibliothèque individuelles telles que std::copy_if) ne peut être effectuée que dans le système de construction de votre application (exécuter le code avec la fonctionnalité, vérifier si elle a compilé et produit des résultats corrects - autoconfest l'outil de choix si vous prenez cette route).

pmr
la source
Il ne semble pas que les fournisseurs de compilateurs mettent à jour cela - peut-être qu'ils attendent d'être pleinement conformes à la norme? ( Stackoverflow.com/q/14131454/11698 )
Richard Corden
2
@prnr: C'est peut-être vrai, mais c'est à l'utilisateur qui a posé la question de décider quelle réponse accepter. Au moment où la réponse qui est actuellement marquée comme acceptée a été publiée, elle était correcte, donc l'affiche originale l'a acceptée. Cet utilisateur peut décider de modifier la réponse acceptée, mais il se peut qu'il ne soit plus actif sur le site. Voir: meta.stackexchange.com/questions/120568/…
Dan Korn
3
vs2017 donne la valeur de __cplusplus 199711
Al Mamun
5
@AlMamun Microsoft partiellement corrigé __cplusplusuniquement dans VS 15.7. Voir leur blog de l'équipe Visual C ++
Ivan_Bereziuk
1
Le lien vers la FAQ est rompu.
brainplot
38

Veuillez exécuter le code suivant pour vérifier la version.

#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";
}
Deepanshu
la source
8
C'est drôle, car sur les studios visuels, la valeur de __cplusplus est 199711L et le code que vous avez posté a renvoyé c ++ 98 cependant, j'ai utilisé des fonctionnalités de c ++ 14, y compris des modèles de variables et decltype (auto). Est-il possible que la mauvaise version de la macro ait été implémentée?
Colin Hicks
2
Voir: devblogs.microsoft.com/cppblog/… (TLDR: spécifiez le drapeau /Zc:__cplusplus)
Daan Timmer
@DaanTimmer Je suis confus par cet article, il semble supposer que vous savez comment utiliser le /Zc:__cplusplusdrapeau. Je ne peux pas simplement std::cout << /Zc:__cplusplus;parce que les deux-points et les barres obliques ne peuvent pas faire partie des noms de variables bien sûr. Êtes-vous en mesure d'expliquer comment procéder? Merci.
A__
7

En fonction de ce que vous souhaitez réaliser, Boost.Config peut vous aider. Il ne fournit pas de détection de la version standard, mais il fournit des macros qui vous permettent de vérifier la prise en charge de certains langages / fonctionnalités du compilateur.

Björn Pollex
la source
3
La vérification des fonctionnalités est probablement une meilleure idée que la vérification des versions standard, de toute façon. Peu de compilateurs prennent en charge tout à partir d'une norme, mais s'ils prennent tous en charge le nombre limité de fonctionnalités dont vous avez besoin, peu importe si les autres fonctionnalités d'une norme donnée sont implémentées et fonctionnent correctement.
Rob Kennedy
4

__cplusplus

Dans C ++ 0x, la macro __cplusplus sera définie sur une valeur différente de (supérieure à) la valeur 199711L actuelle.

FAQ C ++ 0x par BS

Vinzenz
la source
0

Après un rapide google :

__STDC__et __STDC_VERSION__, voir ici

Tor Valamo
la source
Le __STDC__fait de savoir si est défini et sa valeur sont définis par l'implémentation en C ++.
Rob Kennedy
@Rob: Oui, ça l'est. @Tor: J'ai essayé dans VC ++ 2005 mais cela dit que STDC est un identifiant non déclaré. Il est cependant répertorié comme l'une de ces macros prédéfinies. Cependant, STDC_VERSION n'existe pas.
jasonline
Cela vous indique la version du langage de programmation C pris en charge par le compilateur. Il ne vous dit rien sur la version du langage C ++ qui est prise en charge.
Dan Moulding
0

Normalement, vous devez utiliser __cplusplusdefine pour détecter C ++ 17, mais par défaut le compilateur Microsoft ne définit pas correctement cette macro, voir https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ - vous avez besoin pour modifier les paramètres du projet pour inclure le /Zc:__cpluspluscommutateur, ou vous pouvez utiliser une syntaxe comme celle-ci:

#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
     //C++17 specific stuff here
#endif
TarmoPikaro
la source