How are the __cplusplus directive defined in various compilers?
Categories:
Understanding the __cplusplus Directive Across C++ Compilers

Explore how the __cplusplus preprocessor directive is defined by various C++ compilers, its historical evolution, and how to use it for conditional compilation based on C++ standard versions.
The __cplusplus preprocessor directive is a fundamental tool for C++ developers, allowing code to adapt to different C++ language standards. This macro is automatically defined by C++ compilers and expands to a long integer literal that indicates the version of the C++ standard being used. Understanding its values across various compilers and standards is crucial for writing portable and future-proof C++ code.
The Purpose of __cplusplus
The primary purpose of __cplusplus is to enable conditional compilation. Developers can use #if or #ifdef directives to include or exclude specific blocks of code based on the C++ standard supported by the compiler. This is particularly useful when leveraging new language features, deprecating old ones, or providing compatibility layers for different C++ versions. For instance, you might want to use C++11's std::thread if available, but fall back to platform-specific threading APIs on older compilers.
#include <iostream>
int main() {
std::cout << "__cplusplus value: " << __cplusplus << std::endl;
#if __cplusplus >= 201103L
std::cout << "C++11 or later detected." << std::endl;
#elif __cplusplus >= 199711L
std::cout << "C++98/03 detected." << std::endl;
#else
std::cout << "Older C++ standard or non-standard compiler." << std::endl;
#endif
return 0;
}
Basic usage of __cplusplus for version detection
Historical Evolution of __cplusplus Values
The value of __cplusplus has evolved with each new C++ standard. Initially, it was simply 1 for C++98. However, with the introduction of C++11, a more structured approach was adopted, using a YYYYMM format (or YYYYMMLL for C++11 and later) to represent the standard's publication date. This allows for more granular detection of standard versions.

Standard __cplusplus values over time
L suffix (e.g., 201103L) when comparing __cplusplus values. This ensures the literal is treated as a long integer, matching the type of the __cplusplus macro.Compiler-Specific Behaviors and Flags
While the C++ standard specifies the values for __cplusplus, some compilers historically deviated or required specific flags to enable the correct value. For example, older versions of GCC and Clang might require the -std=c++11 or -std=c++14 flag to define __cplusplus correctly for those standards. Microsoft Visual C++ (MSVC) has its own set of predefined macros and historically did not update __cplusplus to the standard-mandated values by default, instead providing _MSVC_LANG for this purpose. However, modern MSVC versions (from Visual Studio 2015 Update 3 onwards) can define __cplusplus correctly when using the /Zc:__cplusplus compiler option.
#if defined(_MSVC_LANG) && _MSVC_LANG >= 201703L
// MSVC with C++17 or later
std::cout << "MSVC C++17 or later detected via _MSVC_LANG." << std::endl;
#elif __cplusplus >= 201703L
// Other compilers with C++17 or later, or MSVC with /Zc:__cplusplus
std::cout << "C++17 or later detected via __cplusplus." << std::endl;
#else
std::cout << "Older C++ standard or different compiler." << std::endl;
#endif
Handling MSVC's _MSVC_LANG alongside __cplusplus
__cplusplus and compiler-specific macros like _MSVC_LANG or _MSC_VER to ensure accurate standard detection.Practical Application: Feature Detection
Beyond simply detecting the C++ standard, __cplusplus is often used in conjunction with other feature-test macros (like __has_include or __cpp_lib_filesystem) to detect the availability of specific language or library features. This allows for highly granular control over code paths, ensuring that your application compiles and runs correctly across a wide range of compiler environments and C++ standard versions.
graph TD
A[Start]
B{Compiler supports C++17?}
C{MSVC with /Zc:__cplusplus?}
D{Use C++17 features}
E{MSVC with _MSVC_LANG >= 201703L?}
F{Use C++17 features (MSVC specific)}
G{Use C++14 features}
H[End]
A --> B
B -- Yes --> D
B -- No --> C
C -- Yes --> D
C -- No --> E
E -- Yes --> F
E -- No --> G
D --> H
F --> H
G --> HDecision flow for C++17 feature detection across compilers