1. Problem It Solves
Projects need one repeatable way to request C++23 and a separate way to test individual facilities. CMake expresses the build requirement; feature-test macros describe the code capability. The goal is to make the relevant rule visible in code instead of relying on an assumption about what “C++23 support” means.
2. Prerequisites
Day 1: compiler identity, standard mode, and incomplete feature support.
3. Core Idea
CMake chooses the lane, while feature-test macros inspect the equipment in the vehicle. A compiler matrix repeats that check across vendors and versions. Read the syntax from left to right, identify the value, object, or range being transformed, and then check its resulting type, lifetime, or ownership. Standardization and implementation are separate: a C++23 mode may still lack one library component, so a feature-test macro is part of responsible portable use.
4. Minimal Syntax
#include <version>
#if defined(__cpp_lib_expected)
#endif5. How It Works
The sample builds the smallest expression or object needed for CMake C++23, Feature-Test Macros, and Compiler Matrices.
It reports selected language and library macros after the build requests C++23. The compiler and library apply the relevant rule before the program observes the result.
The program prints or checks the exact feature values supplied by this libstdc++ installation, making the important behavior easy to verify.
6. Common Mistakes
Using only
CXX_STANDARD 23without checking a new library component confuses requested mode with implemented support.Enabling C++23 mode without checking the relevant feature macro may select code that the installed compiler or standard library does not implement yet.
7. When to Use It
Use it when the task involves a multi-platform repository or any lesson that may run on several compiler versions.
Avoid it when the task involves scattering vendor-number checks through code when a standardized feature macro exists.
8. Simple Example
A project enables an optional std::expected path only when __cpp_lib_expected has a sufficient value. The downloadable program keeps the data fixed so the output can be compared without entering input.
Complete sample code
Source file
cpp23/02_cmake_feature_test_compiler_matrix/main.cpp
#include <iostream>
#include <version>
int main() {
std::cout << "C++ mode=" << __cplusplus << '\n';
#ifdef __cpp_if_consteval
std::cout << "if consteval=" << __cpp_if_consteval << '\n';
#else
std::cout << "if consteval=unavailable\n";
#endif
#ifdef __cpp_lib_expected
std::cout << "expected=" << __cpp_lib_expected << '\n';
#else
std::cout << "expected=unavailable\n";
#endif
}
9. Key Takeaways
Separate the language rule from compiler and library availability.
Keep lifetime, ownership, and deduced types visible when they affect correctness.
Prefer the smallest syntax that communicates the intent.
Guard facilities that are not yet uniformly implemented.
10. Self-Check Questions
Easy — What is the smallest syntax in Section 4, and what main job does it perform?
Medium — Read the sample program: which value, type, or branch is observed, and why?
Hard — If CMake requests C++23 but
__cpp_lib_printis absent, which fact should control a call tostd::print, and why?