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

Explore how the __cplusplus
preprocessor directive is defined by various C++ compilers, its historical evolution, and its utility in writing portable code.
The __cplusplus
preprocessor directive is a fundamental feature in C++ development, providing a mechanism to identify the C++ standard version supported by the compiler. This allows developers to write conditional code that adapts to different language features and behaviors. However, the exact value of __cplusplus
can vary significantly between compilers and their versions, leading to potential portability challenges. This article delves into the specifics of how major compilers define this directive and offers guidance on leveraging it effectively.
The Purpose and Evolution of __cplusplus
The __cplusplus
macro is defined by the C++ standard to indicate that the compilation unit is being compiled as C++ code. Its value is an integer literal representing the year and month of the C++ standard version being used. For instance, C++98/03 is represented by 199711L
, C++11 by 201103L
, C++14 by 201402L
, C++17 by 201703L
, and C++20 by 202002L
. Future standards will follow a similar pattern.
Historically, compilers were slow to update this macro, often defining it as 1
or 199711L
even when supporting newer features. This made it difficult to reliably detect modern C++ standards. The situation has improved significantly with recent compiler versions, which now generally define __cplusplus
correctly when the appropriate standard flag (e.g., -std=c++17
, /std:c++latest
) is used.
flowchart TD A["Start Compilation"] --> B{"Is `__cplusplus` defined?"} B -- Yes --> C{"Compiler supports C++ standard?"} C -- Yes --> D["Set `__cplusplus` to standard value"] C -- No --> E["Set `__cplusplus` to `199711L` (or `1`)"] B -- No --> F["Compile as C (or error)"] D --> G["Conditional Compilation"] E --> G F --> G G --> H["End Compilation"] subgraph Compiler Behavior D E end
General flow of __cplusplus
definition during compilation
Compiler-Specific __cplusplus
Definitions
While the standard dictates the values, real-world compiler implementations have nuances. It's crucial to understand how different compilers behave.
GCC (GNU Compiler Collection)
GCC generally adheres to the standard. When compiling with -std=c++XX
(e.g., -std=c++17
), __cplusplus
will be set to the corresponding standard value. If no specific standard is requested, it often defaults to a value reflecting the latest supported standard or a specific older standard depending on the version.
Clang (LLVM Compiler Frontend)
Clang also follows the standard closely. Similar to GCC, using -std=c++XX
will set __cplusplus
appropriately. Clang is known for its good compliance with C++ standards.
MSVC (Microsoft Visual C++)
Microsoft Visual C++ historically defined __cplusplus
as 199711L
by default, regardless of the C++ standard version it actually supported. This was a significant source of frustration for developers. However, starting with Visual Studio 2017 version 15.7, MSVC introduced the /Zc:__cplusplus
compiler option. When enabled, this option makes __cplusplus
report the correct standard version. Without it, it defaults to 199711L
for backward compatibility.
Other Compilers (Intel C++, Embarcadero C++ Builder, etc.)
Other compilers generally aim to follow the standard, but their default behaviors or specific flags might vary. Always consult the documentation for your specific compiler and version.
#include <iostream>
int main() {
std::cout << "__cplusplus: " << __cplusplus << std::endl;
#if __cplusplus >= 202002L
std::cout << "C++20 or later detected." << std::endl;
#elif __cplusplus >= 201703L
std::cout << "C++17 or later detected." << std::endl;
#elif __cplusplus >= 201402L
std::cout << "C++14 or later detected." << std::endl;
#elif __cplusplus >= 201103L
std::cout << "C++11 or later detected." << std::endl;
#else
std::cout << "Pre-C++11 or unknown standard detected." << std::endl;
#endif
return 0;
}
Example C++ code to check the __cplusplus
value and conditionally compile.
/Zc:__cplusplus
to your compiler options to get the correct __cplusplus
value. This is crucial for modern C++ feature detection.Writing Portable Code with __cplusplus
To write robust and portable C++ code that adapts to different compiler versions and standards, it's best practice to use __cplusplus
for conditional compilation. However, be mindful of the historical quirks, especially with older MSVC versions.
For detecting specific features that might not directly map to a standard version (e.g., specific library features), it's often better to use feature test macros (like __has_include
, __cpp_lib_filesystem
, etc.) if available, as they provide more granular control and are less prone to compiler-specific __cplusplus
issues. However, for broad standard version checks, __cplusplus
remains the primary mechanism.
GCC/Clang
Compile for C++17
g++ -std=c++17 your_code.cpp -o your_program
Compile for C++20
clang++ -std=c++20 your_code.cpp -o your_program
MSVC
Compile for C++17 with correct __cplusplus
cl /std:c++17 /Zc:__cplusplus your_code.cpp
Compile for C++20 (latest) with correct __cplusplus
cl /std:c++latest /Zc:__cplusplus your_code.cpp