Skip to content

/codes/cpp/cplusplus-macro-values

__cplusplus values: which number means which C++ standard (199711L to 202302L)

verified onenvironmentlocal · linux 6.18.44-fc-v236 x64 · GNU bash 5.2.21updated
tool
C++
versions
C++98, C++11, C++14, C++17, C++20, C++23
os
any

__cplusplus is a predefined macro that expands to a number of the form yyyymmL, and the number tells you which C++ standard the compiler is using for this build: 199711L for C++98, 201103L for C++11, 201402L for C++14, 201703L for C++17, 202002L for C++20 and 202302L for C++23 (some older compilers print 202100L for -std=c++23). The GCC manual lists these values under standard predefined macros. In a C compiler the macro is not defined, which is how headers tell the two languages apart.

Values

C++ standard__cplusplusGCC -std value
C++98 (1998)199711L-std=c++98 (or -ansi)
C++11201103L-std=c++11
C++14201402L-std=c++14
C++17201703L-std=c++17
C++20202002L-std=c++20
C++23202302L (GCC 13.3 prints 202100L, see below)-std=c++23

The GNU dialects (-std=gnu++17 and so on) keep the same __cplusplus value and add GNU extensions. For experimental modes the macro is a value larger than the last published standard.

Check it with your compiler

bash
for std in c++98 c++11 c++14 c++17 c++20 c++23; do
  printf '%s: ' "$std"
  echo '__cplusplus' | g++ -std=$std -x c++ -E -P - | tail -n 1
done

Output

c++98: 199711L
c++11: 201103L
c++14: 201402L
c++17: 201703L
c++20: 202002L
c++23: 202100L

On the GCC 13.3 used for this check, -std=c++23 prints 202100L, not the 202302L that the manual lists for the 2023 standard. A compiler that implements C++23 only partly can report a different value, so test __cplusplus >= 202100L when you need to accept such compilers, or use feature-test macros.

Reading the number

The first four digits are the year and the last two the month of the standard's version, so 201703L is 2017-03. Use >= rather than == so that code for C++17 also builds in C++20:

cpp
#if __cplusplus >= 201703L
// C++17 or later
#endif

Pitfalls

  • The value follows the flags, not the compiler. A new compiler with an old -std still reports the old number. Print the real compile command (make V=1, cmake --build . --verbose).
  • MSVC differs. It leaves __cplusplus at 199711L unless /Zc:__cplusplus is set; use _MSVC_LANG there.
  • Feature-test macros are more precise. __cpp_if_consteval, __cpp_lib_expected and similar macros state whether one feature exists, even in a partial implementation.

The flag itself is set when you compile, see compile a C++ program. For what each standard added, read C++20 to C++23. A feature that is missing under the selected standard often appears as was not declared in this scope.

FAQ

How do I check the C++ standard at compile time?

Compare the __cplusplus macro: #if __cplusplus >= 201703L selects code for C++17 and later. It is a long integer of the form yyyymm. For single features prefer the __cpp_* feature-test macros, which tell you what the compiler really supports.

Why does __cplusplus show 199711L when I use a newer compiler?

The macro reflects the standard selected for the compilation, not the compiler's age. If the -std flag asks for C++98, or the build system passes an old value, you get 199711L. Check the flags in the real compile command.

Is __cplusplus the same as _MSVC_LANG?

No. MSVC historically keeps __cplusplus at 199711L unless /Zc:__cplusplus is given, and offers _MSVC_LANG with the real value. Portable code often tests both. GCC and Clang set __cplusplus correctly from the -std flag.

Sources