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
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:
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 current199711L
.
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
:
__cplusplus
is 1
.__cplusplus
is 199711L
.__cplusplus
is 201103L
.__cplusplus
is 201402L
.__cplusplus
is 201703L
.__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).
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";
}
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.
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
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.
__cplusplus
In C++0x the macro __cplusplus will be set to a value that differs from (is greater than) the current 199711L.
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/
After a quick google:
__STDC__
and __STDC_VERSION__
, see here
For cmake projects can use:
if(MSVC)
target_compile_options(mytarget PUBLIC "/Zc:__cplusplus")
endif()
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.