213

How do you determine what version of the C++ standard is implemented by your compiler? As far as I know, below are the standards I've known:

  • C++03
  • C++98
jasonline
  • 8,646
  • 19
  • 59
  • 80
  • 4
    You tagged this *c++*, but two of the three standards you listed are not C++ standards. Which language(s) are you interested in? – Rob Kennedy Feb 24 '10 at 08:56
  • @Rob: Sorry, I'm interested in C++ standards. I'm not sure what other C++ standard versions are there. – jasonline Feb 24 '10 at 09:05
  • Agreed about C99 and C90 - but there is a case for detecting whether you're on a C++ compiler or on C - there are libraries used on both. Also, there's still C++98 and C++03 (and perhaps some major pre-standard variant) to consider - and C++0x2010 of course (the standards guys say something about hex years - I assume that's what they mean). –  Feb 24 '10 at 09:14
  • My bad - I just realised they probably mean C++0x200F - a whole year earlier that what I said before. –  Feb 24 '10 at 09:43
  • I think it's a really strange question. How do I know I'm writing in English? (And a list of which compiler supports what standard is bound to go stale.) – Mat Aug 20 '11 at 14:56
  • 1
    And the question has been asked just a couple minutes ago. (http://stackoverflow.com/questions/7132440/c-developer-and-applications) – Mat Aug 20 '11 at 14:57
  • 1
    @Mat: Posed and closed because the question was rubbish and had some other arbitrary nonsense piggybacking on it. I have re-posted it in a decent form. I'd be happy to close this one if it looks like the original will be fixed and revived, but I'm not holding my breath. – Lightness Races in Orbit Aug 20 '11 at 14:58
  • 1
    @Mat: Well, the best answer is not a static list of compilers, but _a means of determining for yourself_ what is in use. So there you go. – Lightness Races in Orbit Aug 20 '11 at 15:00
  • @Tomalak Geret'kal: Because **FAQ** stands for **Frequently Asked Question**, And this may be frequently referred or answered but this is definitely not frequently asked. – Alok Save Aug 20 '11 at 15:02
  • 1
    @Als: It will be soon. I promise. Besides, the `c++-faq` tag doesn't have any _actual_ pre-requisite "number of times asked" that you have to pass; it's more about the format and generality of the thing. – Lightness Races in Orbit Aug 20 '11 at 15:03
  • @Mat: Oh, balls. I don't really know what the procedure here is; I'd like to see that question updated, but I can't see how it would garner enough interest for the _answers_ to be properly updated too. – Lightness Races in Orbit Aug 20 '11 at 15:05
  • pmr's and Als's answers are already present in that question's answers. Edit the question to add C++0x (whatever it's called now), and upvote the ones with merit - it'll garner attention if people find it attention-worthy. – Mat Aug 20 '11 at 15:07
  • @Mat: I was hoping that this question would include specifics on how to know _which_ C++0x features your compiler supports, how to enable/disable C++11 mode, and such like. But, meh, I suppose you're probably right... – Lightness Races in Orbit Aug 20 '11 at 15:09
  • There is already another one that popped and it essentially asks the same, I think all the 3 should be just merged under a decent title. – Alok Save Aug 20 '11 at 15:09
  • Nah, I give up. :) Sorry all. – Lightness Races in Orbit Aug 20 '11 at 15:12
  • @Tomalak Geret'kal: `c++-faq tag doesn't have any actual pre-requisite` is incorrect and you will notice that if you read the disclaimer/footer that is put with every faq question answer. – Alok Save Aug 20 '11 at 15:13
  • @Tomalak: detecting/turning on/off features is, IMO, a different question (no idea if/how that can be done too). That could be interesting. – Mat Aug 20 '11 at 15:13
  • 1
    I did some digging. This question is a dupe but the answer is flat out not helpful. (See my answer.) So we can go either to improve the old question and make it a `faq` or start a new with this one and get a really comprehensive answer. – pmr Aug 20 '11 at 15:14
  • @Mat: Well it's all the same thing. Detecting features _is_ akin to knowing what [parts of] standard[s] you're using. It's not cut and dry. Were I to have a reasonable answer formulated yet, I'd make the case that there is a vast grey area between the standards now, and this is only going to get worse as C++0x support widens and as C++11 permeates the homeplace. – Lightness Races in Orbit Aug 20 '11 at 15:15
  • @pmr: I agree. I already asked a mod to delete this question, but I think we should decide between what you said. – Lightness Races in Orbit Aug 20 '11 at 15:15
  • @Als: Sorry, but I've run out of having any idea what you're talking about. [edit: OK, the `c++-faq` tag wiki covers what you're saying.] – Lightness Races in Orbit Aug 20 '11 at 15:16
  • @Tomalak I suppose this means the SO chat. – pmr Aug 20 '11 at 15:17
  • @Tomalak Geret'kal: You may want to discuss this belief of yours that there is `no actual pre-requisite "number of times asked" that you have to pass` in the C++ Lounge because the very folks who started this and the very place this was discussed mandated that a FAQ should have that pre-requisite. – Alok Save Aug 20 '11 at 15:19
  • For context, parts of [another question](http://stackoverflow.com/questions/7132498/how-do-i-know-which-c-im-using) have just been merged into this one. Unfortunately, SO does not mark on the merge target that a merge has occurred. – Lightness Races in Orbit Aug 20 '11 at 15:38
  • @Tomalak I usually leave a comment when I merge, and I'm not quite sure why I forgot to do that this time. Sorry. That is an annoying part of the system, I've been considering asking for a feature to make it a bit less subtle. But, I think it's supposed to be subtle by design. – Tim Post Aug 20 '11 at 15:50
  • @TimPost: That would make sense; subtlety and transparency are great, but for an old question like this one it's just downright confusing! :) – Lightness Races in Orbit Aug 20 '11 at 16:22
  • @jasonline - Forgive me for speaking out of turn, but I think pmr's answer should probably be accepted. – jww Apr 22 '18 at 02:00

10 Answers10

377

From the Bjarne Stroustrup C++0x FAQ:

__cplusplus

In C++11 the macro __cplusplus will be set to a value that differs from (is greater than) the current 199711L.

Although this isn't as helpful as one would like. gcc (apparently for nearly 10 years) had this value set to 1, ruling out one major compiler, until it was fixed when gcc 4.7.0 came out.

MSVC also doesn't set this macro correctly, to this very day. By default it's defined to 199711L regardless of the language version, and you either need to add /Zc:__cplusplus to compiler flags, or check a MSVC-specific macro _MSVC_LANG instead, which always has the right value.

These are the C++ standards and what value you should be able to expect in __cplusplus:

  • C++ pre-C++98: __cplusplus is 1.
  • C++98: __cplusplus is 199711L.
  • C++98 + TR1: This reads as C++98 and there is no way to check that I know of.
  • C++11: __cplusplus is 201103L.
  • C++14: __cplusplus is 201402L.
  • C++17: __cplusplus is 201703L.
  • C++20: __cplusplus is 202002L.

If the compiler might be an older gcc, we need to resort to compiler specific hackery (look at a version macro, compare it to a table with implemented features) or use Boost.Config (which provides relevant macros). The advantage of this is that we actually can pick specific features of the new standard, and write a workaround if the feature is missing. This is often preferred over a wholesale solution, as some compilers will claim to implement C++11, but only offer a subset of the features.

The Stdcxx Wiki hosts a comprehensive matrix for compiler support of C++0x features (archive.org link) (if you dare to check for the features yourself).

Unfortunately, more finely-grained checking for features (e.g. individual library functions like std::copy_if) can only be done in the build system of your application (run code with the feature, check if it compiled and produced correct results - autoconf is the tool of choice if taking this route).

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
pmr
  • 58,701
  • 10
  • 113
  • 156
  • Doesn't look like compiler vendors are updating this - maybe they're waiting until they fully conform to the standard?(http://stackoverflow.com/q/14131454/11698) – Richard Corden Jan 22 '13 at 16:44
  • @RichardCorden clang already defines this macro, even though the support for C++11 is partial. – pmr Jan 23 '13 at 11:19
  • 2
    @prnr: That may be true, but it's up to the user who asked the question to decide which answer to accept. At the time that the answer which is currently marked as accepted was posted, it was correct, so the original poster accepted it. That user could decide to change the accepted answer, but they may no longer be active on the site. See: http://meta.stackexchange.com/questions/120568/is-it-possible-to-change-the-chosen-answer – Dan Korn Aug 18 '16 at 19:26
  • The latest version of the Code::Blocks IDE (v 16.01), with MinGW, as of 12 Aug 2017, returns `201300` as the value of `__cplusplus`. – Gabriel Staples Aug 12 '17 at 14:30
  • 3
    vs2017 gives __cplusplus's value 199711 – Al Mamun Dec 13 '17 at 11:18
  • Clang 4.0 is still advertising C++98. That's on Fedora 27 in 2018. Also see [Issue 35853, Clang 4.0 still uses C++98 by default](https://bugs.llvm.org/show_bug.cgi?id=35853) – jww Jan 08 '18 at 03:19
  • 6
    @AlMamun Microsoft partly fixed `__cplusplus` only in VS 15.7. See their [Visual C++ Team Blog](https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus) – Ivan_a_bit_Ukrainivan Jul 04 '18 at 09:51
  • 2
    The link to the FAQ is broken. – brainplot Apr 29 '19 at 02:13
  • CppReference keeps an up-to-date list of the `__cplusplus` here: https://en.cppreference.com/w/cpp/preprocessor/replace#Predefined_macros. – Matt Eding Dec 23 '20 at 20:49
  • It would be nice if the answer itself would mention `/Zc:__cplusplus` for MSVC compilers. – rozina Jan 27 '22 at 12:47
136

Please, run the following code to check the version.

#include<iostream>

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

 
Yuval Zilber
  • 131
  • 11
Deepanshu
  • 1,385
  • 1
  • 7
  • 2
  • 22
    Its funny, because on visual studios the value of __cplusplus is 199711L and the code you posted returned c++98 however, I've used features from c++14 including variable templates and decltype(auto). Is it possible the wrong version of the macro was implemented? – Colin Hicks May 11 '19 at 19:37
  • 3
    See: https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ (TLDR: specify the flag `/Zc:__cplusplus`) – Daan Timmer Aug 12 '19 at 22:08
  • 1
    @DaanTimmer I'm confused by that article, it seems to assume knowledge of how to use the `/Zc:__cplusplus` flag. I can't simply `std::cout << /Zc:__cplusplus;` because colons and slashes can't be part of variable names of course. Are you able to explain how to do this? Thanks. – A__ Oct 31 '19 at 15:12
  • 2
    Found it: https://learn.microsoft.com/en-us/cpp/build/reference/zc-cplusplus?view=vs-2017#to-set-this-compiler-option-in-visual-studio – A__ Oct 31 '19 at 18:41
  • I question the C++23 case, see https://en.cppreference.com/w/cpp/preprocessor/replace#Predefined_macros – Wolf Jun 30 '23 at 12:12
17

By my knowledge there is no overall way to do this. If you look at the headers of cross platform/multiple compiler supporting libraries you'll always find a lot of defines that use compiler specific constructs to determine such things:

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

You probably will have to do such defines yourself for all compilers you use.

RED SOFT ADAIR
  • 12,032
  • 10
  • 54
  • 92
13

Normally you should use __cplusplus define to detect c++17, but by default microsoft compiler does not define that macro properly, see https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ - you need to either modify project settings to include /Zc:__cplusplus switch, or you could use syntax like this:

#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
     //C++17 specific stuff here
#endif
TarmoPikaro
  • 4,723
  • 2
  • 50
  • 62
9

Depending on what you want to achieve, Boost.Config might help you. It does not provide detection of the standard-version, but it provides macros that let you check for support of specific language/compiler-features.

Björn Pollex
  • 75,346
  • 28
  • 201
  • 283
  • 5
    Checking for features is probably a better idea than checking standard versions, anyway. Few compilers support *everything* from a standard, but if they all support the limited number of features you need, then it doesn't really matter whether the rest of the features from a given standard are implemented and working correctly. – Rob Kennedy Feb 24 '10 at 10:36
6

__cplusplus

In C++0x the macro __cplusplus will be set to a value that differs from (is greater than) the current 199711L.

C++0x FAQ by BS

Vinzenz
  • 2,749
  • 17
  • 23
4

Use __cplusplus as suggested. Only one note for Microsoft compiler, use Zc:__cplusplus compiler switch to enable __cplusplus

Source https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/

Dmytro
  • 1,290
  • 17
  • 21
0

After a quick google:

__STDC__ and __STDC_VERSION__, see here

Tor Valamo
  • 33,261
  • 11
  • 73
  • 81
  • Whether `__STDC__` is defined, and what its value is, are implementation-defined in C++. – Rob Kennedy Feb 24 '10 at 08:57
  • @Rob: Yes, it is. @Tor: I tried in VC++ 2005 but it says __STDC__ is an undeclared identifier. It is listed as one of those pre-defined macros though. However, __STDC_VERSION__ does not exist. – jasonline Feb 24 '10 at 09:04
  • 3
    This tells you the version of the C programming language supported by the compiler. It tells you nothing about the version of the C++ language that is supported. – Dan Moulding May 08 '12 at 14:29
0

For cmake projects can use:

if(MSVC)
    target_compile_options(mytarget PUBLIC "/Zc:__cplusplus")
endif()

Font: https://peter-bloomfield-online.translate.goog/report-__cplusplus-correctly-with-cmake-and-visual-studio/?_x_tr_sl=en&_x_tr_tl=pt&_x_tr_hl=pt-BR&_x_tr_pto=sc

0

An alternative to using __cplusplus (which is problematic if you are using MSVC - see most of the other answers) is feature test macros introduced in C++11.

https://en.cppreference.com/w/cpp/feature_test

I find it clearer and easier to use a specific feature test rather than checking which standard is active. It is clearer because it identifies what you really want (most standards have a lot of features and you usually don't use all of them). It is easier because often compilers only partially implement a standard so even though you are compiling with a particular standard active you might not get the feature anyway.

Bowie Owens
  • 2,798
  • 23
  • 20