The dark age: __cplusplus plus per-compiler macro matrices; every portable library carries a config header.
#if defined(_MSC_VER) && _MSC_VER < 1900
# define MYLIB_NO_CONSTEXPR
#endif
Feature-test macros, shims, standard-by-standard adoption.
The dark age: __cplusplus plus per-compiler macro matrices; every portable library carries a config header.
#if defined(_MSC_VER) && _MSC_VER < 1900
# define MYLIB_NO_CONSTEXPR
#endif
No relief yet; SD-6 feature-test macro recommendations circulate but are not required.
__has_include enables header-level probing — the first standard detection tool.
#if __has_include(<optional>)
# include <optional>
#endif
<version> lands with ~200 __cpp_lib_* / __cpp_* macros: feature detection becomes per-feature, not per-compiler-version — the idiomatic shim pattern ever since.
#include <version>
#ifdef __cpp_lib_format
# include <format>
# define FMT(...) std::format(__VA_ARGS__)
#else
# define FMT(...) fmt::format(__VA_ARGS__)
#endif
Detection of language features in constant evaluation gets cleaner with if consteval; migration guides increasingly phrase support as paper numbers + macros (the cppstat view of the world).
Contracts and hardening introduce build-mode axes (ignore/observe/enforce) alongside standard version — migration planning becomes two-dimensional: language level and enforcement level.
Direction: profiles (P3081 line) would make opt-in rulesets a third detection axis if adopted.
C++26 per the final working draft; C++29 rows are proposals and direction, not adopted features.