Ch3.15: Feature Testing
What Feature Testing Is
Different compilers, platforms, and standard libraries support different features. Feature testing allows your program to adapt to what is available at compile time.
All feature testing is done by the preprocessor, before the compiler sees your code.
- detecting headers
- detecting compiler features
- detecting platform
- detecting C++ standard version
- detecting library features
- detecting C-level macros from your toolchain
Detecting Headers: __has_include
__has_include checks whether a header exists before including it.
#if __has_include()
#include
#else
println("std::span not available");
#endif
Detecting #embed: __has_embed
__has_embed checks whether the compiler supports the
#embed directive.
#if __has_embed("resource.bin")
static constexpr auto data =
#embed "resource.bin";
#else
print("embed not supported\n");
#endif
Detecting the C++ Standard Version: __cplusplus
The macro __cplusplus indicates which C++ standard the
compiler is using.
#if __cplusplus >= 202002L
print("C++20 or later\n");
#elif __cplusplus >= 201703L
print("C++17\n");
#else
print("older C++\n");
#endif
This macro is defined by the compiler, not the standard library.
Compiler Feature Macros
Compilers define macros that indicate whether certain language features are enabled.
__cpp_exceptions
Defined if exception handling is enabled.
#ifdef __cpp_exceptions
print("exceptions enabled\n");
#else
print("exceptions disabled\n");
#endif
Many environments ban exceptions entirely due to implementation complexity or runtime cost — including Android, WebAssembly, embedded systems, and operating system kernels. We will discuss this in detail in future chapters.
__cpp_rtti
Defined if run-time type information (RTTI) is enabled.
#ifdef __cpp_rtti
print("RTTI enabled\n");
#else
print("RTTI disabled\n");
#endif
Platform Detection
Compilers define macros that identify the operating system.
#ifdef _WIN32
print("Windows\n");
#endif
#ifdef __linux__
print("Linux\n");
#endif
#ifdef __APPLE__
print("macOS\n");
#endif
Compiler Detection
#ifdef __clang__
print("Clang\n");
#endif
#ifdef __GNUC__
print("GCC\n");
#endif
#ifdef _MSC_VER
print("MSVC\n");
#endif
Detecting Library Features: <version> Header
The C++ standard library provides feature-test macros of the form
__cpp_feature. These macros indicate which library features
are available.
They are all defined in the <version> header.
#include
#ifdef __cpp_lib_span
print("std::span available\n");
#else
print("std::span not available\n");
#endif
The complete and authoritative list of feature-test macros is here:
Detecting C Macros: features.h
Your toolchain also provides many C-level feature macros. These are not part of C++, but they affect portability and low-level behavior.
They are usually defined in a header named:
features.h
This header is part of your C library implementation (glibc, musl, BSD libc, etc.). It contains macros such as:
_GNU_SOURCE_POSIX_C_SOURCE_XOPEN_SOURCE_FORTIFY_SOURCE
These macros control which C and POSIX APIs are available.
Check your toolchain’s features.h for the exact list.
Key takeaways
- Feature testing happens before compilation.
- __has_include / __has_embed: detect headers and embed support.
- __cplusplus: detect the C++ language version.
- __cpp_exceptions / __cpp_rtti: detect compiler-level features.
- Platform macros: detect the operating system.
- Compiler macros: detect the compiler.
- <version>: provides C++ standard library feature-test macros.
- features.h: contains C-level feature macros from your toolchain.
- cppreference feature-test list:
https://en.cppreference.com/w/cpp/feature_test.html