How to determine the version of the C++ standard used by the compiler?
C++StandardsC++ Problem Overview
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
C++ Solutions
Solution 1 - C++
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.
These are the C++ standards and what value you should be able to expect in __cplusplus
:
- C++ pre-C++98:
__cplusplus
is1
. - C++98:
__cplusplus
is199711L
. - C++98 + TR1: This reads as C++98 and there is no way to check that I know of.
- C++11:
__cplusplus
is201103L
. - C++14:
__cplusplus
is201402L
. - C++17:
__cplusplus
is201703L
. - C++20:
__cplusplus
is202002L
.
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).
Solution 2 - C++
Please, run the following code to check the 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";
}
Solution 3 - C++
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.
Solution 4 - C++
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.
Solution 5 - C++
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
Solution 6 - C++
> __cplusplus > > In C++0x the macro __cplusplus will be set to a value that differs from (is greater than) the current 199711L.
Solution 7 - C++
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/
Solution 8 - C++
After a quick google:
__STDC__
and __STDC_VERSION__
, see here
Solution 9 - C++
For cmake projects can use:
if(MSVC)
target_compile_options(mytarget PUBLIC "/Zc:__cplusplus")
endif()