What is the value of __cplusplus for C++17? - c++

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.156
156) 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://learn.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.

A modern compile time check that you can put in any file that needs it:
static_assert(__cplusplus >= 201703L, "This file expects a C++17 compatible compiler.");

Related

Is it possible to set g++ to follow C++11 ISO (-std=c++11) through #define?

I'm quite new to c++11 and I was wondering something...
I am using Code::Blocks and if I were to use c++11 in this IDE, i had to go to compiler settings, and and Check "Have g++ follow the C++11 ISO C++ language standard"
Is there any workaround so I can set a single .cpp file to use c++11 in the #define statement like this?
Note: This is a single "Build" file, NOT a project
By setting the compile option while not in project, it'll set it to Global Compile option that I prefer to not happen
I know that you can customize the build option in Project Files that It'll set c++11 for that project only
#include <iostream>
#define -std c++11
int main(){
#if __cplusplus==201402L
std::cout << "C++14" << std::endl;
#elif __cplusplus==201103L
std::cout << "C++11" << std::endl;
#else
std::cout << "C++" << std::endl;
#endif
return 0;
}
What I have found:
Changing #define __cplusplus 201103L is NOT a good idea, because it don't set the compiler to compile as c++11
Although I can see how it would be desirable for a source file to be self-documenting in this respect, this isn't possible.
The next best thing is to test conformance, as you've started to do:
#if __cplusplus < 201103L
#error This source must be compiled as C++11 or later
#endif
That ensures that compilation with a C++03 compiler will give a simple, understandable error message straight away.
Is it possible to set g++ to follow C++11 ISO (-std=c++11) through #define?
No.
Neither C++ nor g++ have that feature. You might want to build simple one-file programs manually.
No.
You shouldn't changing the #define __cplusplus. Read more in How to trigger the __cplusplus (C++) #ifdef?, because __cplusplus should be automatically defined by C++ compiler. That's why changing the version is meant to be done via the compiler settings.
It doesn't make sense to have a file follow C++11, while the others would follow C++14, for example. The whole project should be compiled in a homogeneous way.
Notice that your code wouldn't compile: Error: macro names must be identifiers using #ifdef 0.
PS: What a nightmare it would be in terms of readability and maintenance if what you described was a good idea..

Is there a standard definition for __cplusplus in c++14?

I'm looking to setup some preprocessor stuff, and I'd like a more exact number for what __cplusplus in C++14 should be defined as. Is there one mandated by the standard?
cppreference has information on the standard values of the __cplusplus macro in the section "Predefined macros." Currently the standard values are:
199711L (C++98 or C++03)
201103L (C++11)
201402L (C++14)
201703L (C++17)
202002L (C++20)
The macro's value for any given version isn't firmly established until the final standard is published. Therefore, as of June 2019, there was no way to know what the macro value for C++2a would be (and as of Feb 2021 there's no way to know what the value will be for C++2b).
Library vendors typically gate their "C++2a" features on #if __cplusplus > 201703L, and their "C++2b" features on __cplusplus > 202002L, and so on.
Compiler vendors with a "C++2a" mode simply picked any arbitrary value for __cplusplus that made the library vendors' checks happy:
GCC (8.x thru 10.x) -std=c++2a mode uses __cplusplus == 201709L.
Clang (5.x thru 9.x) -std=c++2a mode uses __cplusplus == 201707L.
Microsoft Visual Studio (19.20 thru 19.28) /std:c++latest mode uses __cplusplus == 201705L if and only if you pass /Zc:__cplusplus! Otherwise it uses 199711L. So watch out for that!
How have transitions historically been handled?:
Clang 4.0.1 -std=c++1z set __cplusplus == 201406L. Clang 5.0.0 introduced -std=c++17 and -std=c++2a, made -std=c++1z a synonym for -std=c++17, and bumped the macro (no matter which of 17/1z you used) to the standard value 201703L. Clang 10.0 introduced -std=c++20, made -std=c++2a a synonym for -std=c++20, and bumped the macro to the standard value 202002L. As of Feb 2021, Clang has no formal "C++2b" mode.
GCC 5.1 introduced -std=c++1z and -std=c++17 as synonyms out of the gate, setting __cplusplus == 201500L. GCC 7.1 bumped the value (no matter which spelling you used) to the standard value of 201703L. GCC 8.1 introduced -std=c++2a with __cplusplus == 201709L. GCC 10.1 introduced -std=c++20 as a synonym for -std=c++2a (but left the macro at 201709L). As of Feb 2021, GCC trunk has introduced -std=c++2b with __cplusplus == 202100L.
Oddly, according to Godbolt Compiler Explorer, MSVC bumped the macro for -std:c++latest mode from 201704L to 201705L sometime between MSVC 19.16 and 19.20. As of Feb 2021, as far as I know, MSVC has no formal "C++20" mode.
N3936* §16.8 [cpp.predefined]/p1:
1 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.
N3936 is the final working draft that became C++14, and the number 201402L is consistent with the meeting at which the C++14 standard is sent out for final balloting (February 2014).
*Those interested in obtaining a copy of the C++ standard should check out Where do I find the current C or C++ standard documents?

Clang >= 3.3 in c++1y mode cannot parse <cstdio> header

I have a project that correctly compiles and runs under g++ 4.8.1 and clang >= 3.3 in c++11 mode. However, when I switch to the experimental -std=c++1y mode, clang 3.3 (but not g++) chokes on the <cstdio> header that is indirectly included by way of Boost.Test (so I cannot easily change it myself)
// /usr/include/c++/4.8/cstdio
#include <stdio.h>
// Get rid of those macros defined in <stdio.h> in lieu of real functions.
// ...
#undef gets
// ...
namespace std
{
// ...
using ::gets; // <-- error with clang++ -std=c++1y
// ...
}
with the following error message:
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/cstdio:119:11:
error: no member named 'gets' in the global namespace
On this tutorial on how to set up a modern C++ environment, a similar lookup problem with max_align_t is encountered. The recommendation there is to use a sed script to surround the unknown symbols with #ifdef __clang__ macros, but that seems a fragile approach.
Setup: plain 64-bit Linux Mint 15 with
g++ (Ubuntu 4.8.1-2ubuntu1~13.04) 4.8.1
Ubuntu clang version 3.3-3~raring1 (branches/release_33) (based on
LLVM 3.3)
Questions:
what is causing this erorr? There is no __clang__ macro anywhere near the code in question, and clang in c++11 mode has no trouble at all.
Is it a language problem (does C++14 say something else than C++11 about importing C compatible symbols from the global into the std namespace)?
Do I need to change something with my include paths? (I use CMake to automatically select the header paths, and switch modes inside CMakeLists.txt)
Does clang have a switch to resolve this?
This note in the gets manpage looks relevant:
ISO C11 removes the specification of gets() from the C language, and since version 2.16, glibc header files don't expose the function declaration if the _ISOC11_SOURCE feature test macro is defined.
Probably should be
#if !_ISOC11_SOURCE
using ::gets;
#endif

Gnu C++ macro __cplusplus standard conform?

The Gnu C++ compiler seems to define __cplusplus to be 1
#include <iostream>
int main() {
std::cout << __cplusplus << std::endl;
}
This prints 1 with gcc in standard c++ mode, as well as in C++0x mode, with gcc 4.3.4, and gcc 4.7.0.
The C++11 FDIS says in "16.8 Predefined macro names [cpp.predefined]" that
The name __cplusplus is defined to the value 201103L when compiling a C++ translation unit. (Footnote: It is intended that future versions of this standard will replace the value of this macro with a greater value. Non-conforming com-
pilers should use a value with at most five decimal digits.)
The old std C++03 had a similar rule.
Is the GCC deliberatly setting this to 1, because it is "non-conforming"?
By reading through that list I thought that I could use __cplusplus to check in a portable way if I have a C++11 enabled compiler. But with g++ this does not seem to work. I know about the ...EXPERIMENTAL... macro, but got curious why g++ is defining __cplusplus this way.
My original problem was switch between different null-pointer-variants. Something like this:
#if __cplusplus > 201100L
# define MYNULL nullptr
#else
# define MYNULL NULL
#endif
Is there a simple and reasonably portable way to implement such a switch?
This was fixed about a month ago (for gcc 4.7.0). The bug report makes for an interesting read: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=1773
If I recall correctly this has to do with Solaris 8 causing issues when __cplusplus is set as it should. The gcc team decided at the time to support the Solaris 8 platform rather than be compliant in this particular clause. But I noticed that the latest version of gcc ends the Solaris 8 support, and I guess this is a first step in the right direction.
It is a very old g++ bug.
That is, the compiler is not conforming.
Apparently it can't be fixed because fixing it would break something on a crazy platform.
EDIT: oh, I see from #birryree's comment that has just been fixed, in version 4.7.0. So, it was not impossible to fix after all. Heh.
Cheers & hth.

conditional compilation statement in limits.h

I am not able to understand the following statement from the file limits.h. What is the use of this statement and what does it accomplishes?
/* If we are not using GNU CC we have to define all the symbols ourself.
Otherwise use gcc's definitions (see below). */
#if !defined __GNUC__ || __GNUC__ < 2
It checks if your program is compiled by some other compiler than GCC, or some very old GCC version.
It checks whether you are not using a Gcc compiler Version 2 or Gcc some other versions.
using this pre-processor macro we can some portable codes.