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: __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:

https://en.cppreference.com/w/cpp/feature_test.html

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:

These macros control which C and POSIX APIs are available. Check your toolchain’s features.h for the exact list.

Key takeaways