What is the value of __cplusplus for C++17?
We are trying to test some code under C++17 and its change to std::uncaught_exception
. I can't seem to get GCC to provide the value of __cplusplus
:
$ /opt/local/bin/g++ -std=c++17 -dM -E - </dev/null | grep __cplusplus
cc1: warning: command line option '-std=c++1z' is valid for C++/ObjC++ but not for C
$
And:
$ /opt/local/bin/g++ --version
g++-mp-6 (MacPorts gcc6 6.1.0_0) 6.1.0
Copyright (C) 2016 Free Software Foundation, Inc.
What is the value of __cplusplus
when using C++17?
tl;dr: For C++17, __cplusplus
is 201703L
.
What is the value of
__cplusplus
when using C++17?
According to the draft standard N4594 §16.8/p1 Predefined macro names [cpp.predefined] (Emphasis Mine):
The following macro names shall be defined by the implementation:
__cplusplus
The name__cplusplus
is defined to the value 201402L when compiling a C++ translation unit.156156) It is intended that future versions of this standard will replace the value of this macro with a greater value. Non-conforming compilers should use a value with at most five decimal digits.
However the same value is appointed for the C++14 standard. Apparently it seems so, that there's no official/standard __cplusplus
value set yet for the C++17 standard.
In GCC versions 6.1 and 7.0 the value is changed to 201500
Live Demo
In Clang version 3.8 and 3.9 the value is unchanged 201406.
Consequently, you'll have to wait a little bit for the standard value to come out.
--- Update ---
According to the C++ standard §19.8/p1 Predefined macro names [cpp.predefined] (Emphasis Mine):
1 The following macro names shall be defined by the implementation:
__cplusplus
The integer literal 201703L.
Thus, the value of __cplusplus
when using C++17 shall be 201703L.
I would try:
#if __cplusplus > 201402L
// C++14 code here
...
#endif
In other words, testing for greater than C++14 should work as compilers add more features. As someone mentioned above, GCC uses 201500L
. It looks like clang uses 201406L
(four months after C++14 I guess).
Using the above snippet should be cross-platform and will work even when C++17 comes out with real value for __cplusplus
. For more details about evolving features try the feature test macros.
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
I realize you asked this question citing the Gnu C++ compiler as the one you're using, but you may want to have some awareness of what happens on the Visual C++ compiler, and strictly speaking, your question didn't ask about a specific compiler.
Currently, as of the date of this posting, the VC++ 2017 compiler sets __cplusplus
to 199711L
rather than what you might expect if you set the compiler to use c++17.
To get it to report correctly, you have to also set /Zc:__cplusplus
.
(source: https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus?view=vs-2017 )
As to why? Well... in their words:
We tried updating the macro by default and discovered that a lot of code doesn’t compile correctly when we change the value of __cplusplus.
(source: https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/)
I don't really know why __cplusplus
doesn't show up as a regular macro, but I'm guessing it's so you can't redefine it. This is how I determine the its value.
#include <iostream>
int main( int argc, char** argv )
{
std::cout << __cplusplus << std::endl;
return 0;
}
Then compilation shows the value.
$ g++-6 test.cpp && ./a.out
201402
$ g++-6 -std=c++17 test.cpp && ./a.out
201500
I would check whether it's >= 201500
as opposed to checking for any specific value.