Пространства имён
Варианты
Действия

Макросы проверки возможностей (начиная с C++20)

Материал из cppreference.com
< cpp

Стандарт определяет набор макросов препроцессора, соответствующих языку C++ и возможностям библиотеки, представленным в C++11 или новее. Они предназначены как простой и портабельный способ проверки наличия указанных возможностей.

Содержание

[править] Атрибуты

__has_cpp_attribute( маркер-атрибута )

Проверяет поддержку атрибута с именем маркер-атрибута (после раскрытия макроса).

Для каждого стандартного атрибута реализация определяет, расширяется ли __has_cpp_attribute до значения, указанного в таблице ниже (это год и месяц, в которых атрибут был добавлен в рабочий проект) или 0. Он расширится до заданного значения в таблице тогда и только тогда, когда стандартный атрибут заставляет реализацию вести себя так, как рекомендовано (выдача диагностических сообщений, влияние на структуру классов и т.д.).

Наличие атрибутов, специфичных для поставщика, определяется ненулевым значением.

__has_cpp_attribute можно разложить на выражение #if и #elif. Он рассматривается как определённый макрос для #ifdef, #ifndef, #elifdef, #elifndef (начиная с C++23) и defined, но не может быть использован где-либо еще.

маркер-атрибута Атрибут Значение Стандарт Документ(ы)
assume [[assume]] 202207L (C++23) P1774R8
carries_dependency [[carries_dependency]] 200809L (C++11) N2556, N2643
deprecated [[deprecated]] 201309L (C++14) N3760
fallthrough [[fallthrough]] 201603L (C++17) P0188R1
likely [[likely]] 201803L (C++20) P0479R5
maybe_unused [[maybe_unused]] 201603L (C++17) P0212R1
no_unique_address [[no_unique_address]] 201803L (C++20) P0840R2
nodiscard [[nodiscard]] 201603L (C++17) P0189R1
201907L (C++20) P1301R4
noreturn [[noreturn]] 200809L (C++11) N2761
unlikely [[unlikely]] 201803L (C++20) P0479R5
Общее количество атрибутов: 10

[править] Возможности языка

Следующие макросы предопределены в каждой единице трансляции. Каждый макрос расширяется до целочисленного литерала, соответствующего году и месяцу, когда соответствующая возможность была включена в рабочий черновик.

Когда возможность значительно изменится, макрос будет обновлён соответствующим образом.

Имя макроса Возможность Значение Стд
__cpp_aggregate_bases Агрегирование классов с базовыми классами 201603L (C++17)
__cpp_aggregate_nsdmi Агрегирование классов с инициализаторами элементов по умолчанию 201304L (C++14)
__cpp_aggregate_paren_init Агрегированная инициализация в форме прямой инициализации 201902L (C++20)
__cpp_alias_templates Шаблоны псевдонимов 200704L (C++11)
__cpp_aligned_new Динамическое выделение памяти для данных с нестандартным выравниванием 201606L (C++17)
__cpp_attributes Атрибуты 200809L (C++11)
__cpp_binary_literals Двоичные литералы 201304L (C++14)
__cpp_capture_star_this Лямбда-захват *this по значению как [=,*this] 201603L (C++17)
__cpp_char8_t char8_t 201811L (C++20)
__cpp_concepts Концепты 201907L (C++20)
__cpp_conditional_explicit explicit(bool) 201806L (C++20)
__cpp_consteval Немедленно выполняемые функции 201811L (C++20)
__cpp_constexpr constexpr 200704L (C++11)
Ослабленный constexpr, не-const constexpr методы 201304L (C++14)
Constexpr лямбда 201603L (C++17)
Тривиальный инициализация по умолчанию и объявление asm в constexpr функциях 201907L (C++20)
__cpp_constexpr_dynamic_alloc Операции для динамической длительности хранения в constexpr функциях 201907L (C++20)
__cpp_constexpr_in_decltype Создание определений функций и переменных, когда они необходимы для вычисления константы 201711L (C++20)
__cpp_constinit constinit 201907L (C++20)
__cpp_decltype decltype 200707L (C++11)
__cpp_decltype_auto Вывод типа возвращаемого значения для обычных функций 201304L (C++14)
__cpp_deduction_guides Вывод аргументов шаблона для шаблонов классов 201703L (C++17)
CTAD для агрегатов и псевдонимов 201907L (C++20)
__cpp_delegating_constructors Делегирование конструкторов 200604L (C++11)
__cpp_designated_initializers Назначенный инициализатор 201707L (C++20)
__cpp_enumerator_attributes Атрибуты для нумераторов 201411L (C++17)
__cpp_fold_expressions Выражения свёртки 201603L (C++17)
__cpp_generic_lambdas Общие лямбда-выражения 201304L (C++14)
Знакомый синтаксис шаблона для общих лямбд 201707L (C++20)
__cpp_guaranteed_copy_elision Гарантированный пропуск копирования за счёт упрощённой категории значений 201606L (C++17)
__cpp_hex_float Шестнадцатеричные литералы с плавающей запятой 201603L (C++17)
__cpp_if_consteval consteval if 202106L (C++23)
__cpp_if_constexpr constexpr if 201606L (C++17)
__cpp_impl_coroutine Сопрограммы (поддержка компилятором) 201902L (C++20)
__cpp_impl_destroying_delete Уничтожающий оператор delete (поддержка компилятором) 201806L (C++20)
__cpp_impl_three_way_comparison Трёхстороннее сравнение (поддержка компилятором) 201907L (C++20)
__cpp_inheriting_constructors Наследование конструкторов 200802L (C++11)
Переделка наследуемых конструкторов 201511L (C++17)
__cpp_init_captures Захват при инициализации лямбда 201304L (C++14)
Разрешено расширение пакета в захвате при инициализации лямбда 201803L (C++20)
__cpp_initializer_lists Список инициализации и std::initializer_list 200806L (C++11)
__cpp_inline_variables Встроенные переменные 201606L (C++17)
__cpp_lambdas Лямбда-выражения 200907L (C++11)
__cpp_modules Модули 201907L (C++20)
__cpp_namespace_attributes Атрибуты для пространств имён 201411L (C++17)
__cpp_noexcept_function_type Спецификации исключений сделаны частью системы типов 201510L (C++17)
__cpp_nontype_template_args Разрешено константное вычисление для всех аргументов шаблона, не относящиеся к типу 201411L (C++17)
Типы классов и типы с плавающей запятой в аргументах шаблона не являющихся типами 201911L (C++20)
__cpp_nontype_template_parameter_auto Объявление аргументов шаблона не являющиеся типами с auto 201606L (C++17)
__cpp_nsdmi Инициализаторы нестатических элементов данных 200809L (C++11)
__cpp_range_based_for Основанный на диапазоне цикл for 200907L (C++11)
Цикл for на основе диапазона с разными начальным/конечным типами 201603L (C++17)
__cpp_raw_strings Необработанные строковые литералы 200710L (C++11)
__cpp_ref_qualifiers Квалификаторы ссылок 200710L (C++11)
__cpp_return_type_deduction Вывод типа возвращаемого значения для обычных функций 201304L (C++14)
__cpp_rvalue_references Правосторонняя ссылка 200610L (C++11)
__cpp_size_t_suffix Литеральные суффиксы для size_t и её знаковой версии 202011L (C++23)
__cpp_sized_deallocation Освобождение памяти по размеру 201309L (C++14)
__cpp_static_assert static_assert 200410L (C++11)
Одно-аргументный static_assert 201411L (C++17)
__cpp_structured_bindings Структурные привязки 201606L (C++17)
__cpp_template_template_args Соответствие шаблонным аргументам шаблона 201611L (C++17)
__cpp_threadsafe_static_init Динамическая инициализация и уничтожение с конкуренцией 200806L (C++11)
__cpp_unicode_characters Новые символьные типы (char16_t и char32_t) 200704L (C++11)
__cpp_unicode_literals Строковые литералы в Юникоде 200710L (C++11)
__cpp_user_defined_literals Пользовательские литералы 200809L (C++11)
__cpp_using_enum Using enum 201907L (C++20)
__cpp_variable_templates Шаблоны переменных 201304L (C++14)
__cpp_variadic_templates Вариативные шаблоны 200704L (C++11)
__cpp_variadic_using Расширения пакетов в using-объявлении 201611L (C++17)

[править] Возможности библиотеки

Следующие макросы определены, если включён заголовок <version> или любой из соответствующих заголовков в таблице ниже. Каждый макрос расширяется в целочисленный литерал, соответствующий году и месяцу, когда соответствующая возможность была включена в рабочий черновик.

Когда возможность значительно изменяется, макрос обновляется соответствующим образом.

Имя макроса Возможность Значение Заголовок Стд
__cpp_lib_addressof_constexpr Constexpr std::addressof 201603L <memory> (C++17)
__cpp_lib_allocator_traits_is_always_equal std::allocator_traits::is_always_equal 201411L <memory> <scoped_allocator> <string> <deque> <forward_list> <list> <vector> <map> <set> <unordered_map> <unordered_set> (C++17)
__cpp_lib_any std::any 201606L <any> (C++17)
__cpp_lib_apply std::apply 201603L <tuple> (C++17)
__cpp_lib_array_constexpr Constexpr для std::reverse_iterator, std::move_iterator, std::array и доступа в диапазоне 201603L <iterator> <array> (C++17)
ConstexprIterator; constexpr сравнение для std::array; разные constexpr биты (std::array::fill и другие) 201811L <iterator> <array> (C++20)
__cpp_lib_as_const std::as_const 201510L <utility> (C++17)
__cpp_lib_assume_aligned std::assume_aligned 201811L <memory> (C++20)
__cpp_lib_atomic_flag_test std::atomic_flag::test 201907L <atomic> (C++20)
__cpp_lib_atomic_float Атомарность с плавающей точкой 201711L <atomic> (C++20)
__cpp_lib_atomic_is_always_lock_free constexpr atomic<T>::is_always_lock_free 201603L <atomic> (C++17)
__cpp_lib_atomic_lock_free_type_aliases атомарные целочисленные типы без блокировок (std::atomic_signed_lock_free, std::atomic_unsigned_lock_free) 201907L <atomic> (C++20)
__cpp_lib_atomic_ref std::atomic_ref 201806L <atomic> (C++20)
__cpp_lib_atomic_shared_ptr std::atomic<std::shared_ptr> 201711L <memory> (C++20)
__cpp_lib_atomic_value_initialization Исправление атомарной инициализации (инициализация значения std::atomic по умолчанию) 201911L <atomic> <memory> (C++20)
__cpp_lib_atomic_wait Эффективное std::atomic ожидание 201907L <atomic> (C++20)
__cpp_lib_barrier std::barrier 201907L <barrier> (C++20)
__cpp_lib_bind_front std::bind_front 201907L <functional> (C++20)
__cpp_lib_bit_cast std::bit_cast 201806L <bit> (C++20)
__cpp_lib_bitops Битовые операции 201907L <bit> (C++20)
__cpp_lib_bool_constant std::bool_constant 201505L <type_traits> (C++17)
__cpp_lib_bounded_array_traits std::is_bounded_array, std::is_unbounded_array 201902L <type_traits> (C++20)
__cpp_lib_boyer_moore_searcher Алгоритмы поиска 201603L <functional> (C++17)
__cpp_lib_byte std::byte 201603L <cstddef> (C++17)
__cpp_lib_char8_t Библиотечная поддержка для char8_t 201907L <atomic> <filesystem> <istream> <limits> <locale> <ostream> <string> <string_view> (C++20)
__cpp_lib_chrono Функции округления для std::chrono::duration и std::chrono::time_point 201510L <chrono> (C++17)
Constexpr для всех функций-элементов std::chrono::duration и std::chrono::time_point 201611L <chrono> (C++17)
Календари и Часовые Пояса 201907L <chrono> (C++20)
__cpp_lib_chrono_udls Определяемые пользователем литералы для типов времени 201304L <chrono> (C++14)
__cpp_lib_clamp std::clamp 201603L <algorithm> (C++17)
__cpp_lib_complex_udls Пользовательские литералы для std::complex 201309L <complex> (C++14)
__cpp_lib_concepts Концепты стандартной библиотеки 202002L <concepts> (C++20)
__cpp_lib_constexpr_algorithms Constexpr для алгоритмов 201806L <algorithm> (C++20)
__cpp_lib_constexpr_complex Constexpr для std::complex 201711L <complex> (C++20)
__cpp_lib_constexpr_dynamic_alloc Constexpr для std::allocator и связанных утилит 201907L <memory> (C++20)
__cpp_lib_constexpr_functional Разные constexpr биты (std::default_searcher); constexpr INVOKE 201907L <functional> (C++20)
__cpp_lib_constexpr_iterator Разные constexpr биты (std::insert_iterator и другие) 201811L <iterator> (C++20)
__cpp_lib_constexpr_memory Constexpr в std::pointer_traits 201811L <memory> (C++20)
__cpp_lib_constexpr_numeric Constexpr для числовых алгоритмов 201911L <numeric> (C++20)
__cpp_lib_constexpr_string Constexpr для std::string 201907L <string> (C++20)
__cpp_lib_constexpr_string_view Разные constexpr биты (std::string_view::copy) 201811L <string_view> (C++20)
__cpp_lib_constexpr_tuple Разные constexpr биты (std::tuple::operator= и другие) 201811L <tuple> (C++20)
__cpp_lib_constexpr_typeinfo Constexpr для std::type_info::operator== 202106L <typeinfo> (C++23)
__cpp_lib_constexpr_utility Разные constexpr биты (std::pair::operator= и другие) 201811L <utility> (C++20)
__cpp_lib_constexpr_vector Constexpr для std::vector 201907L <vector> (C++20)
__cpp_lib_coroutine Сопрограммы (поддержка библиотекой) 201902L <coroutine> (C++20)
__cpp_lib_destroying_delete Уничтожение operator delete (поддержка библиотекой) 201806L <new> (C++20)
__cpp_lib_enable_shared_from_this Более точная спецификация std::enable_shared_from_this 201603L <memory> (C++17)
__cpp_lib_endian std::endian 201907L <bit> (C++20)
__cpp_lib_erase_if Равномерная очистка контейнера 202002L <string> <deque> <forward_list> <list> <vector> <map> <set> <unordered_map> <unordered_set> (C++20)
__cpp_lib_exchange_function std::exchange 201304L <utility> (C++14)
__cpp_lib_execution Политики исполнения 201603L <execution> (C++17)
std::execution::unsequenced_policy 201902L <execution> (C++20)
__cpp_lib_filesystem Библиотека файловой системы 201703L <filesystem> (C++17)
__cpp_lib_format Форматирование текста 201907L <format> (C++20)
__cpp_lib_gcd_lcm std::gcd, std::lcm 201606L <numeric> (C++17)
__cpp_lib_generic_associative_lookup Поиск гетерогенным сравнением в [[cpp/container#Ассоциативные контейнеры|ассоциативных контейнерах 201304L <map> <set> (C++14)
__cpp_lib_generic_unordered_lookup Поиск гетерогенным сравнением в ассоциативных контейнерах 201811L <unordered_map> <unordered_set> (C++20)
__cpp_lib_hardware_interference_size [[constexpr std::hardware_{constructive, destructive}_interference_size|hardware_destructive_interference_size|constexpr std::hardware_{constructive, destructive}_interference_size]]]] 201703L <new> (C++17)
__cpp_lib_has_unique_object_representations std::has_unique_object_representations 201606L <type_traits> (C++17)
__cpp_lib_hypot 3-аргументная перегрузка std::hypot 201603L <cmath> (C++17)
__cpp_lib_incomplete_container_elements Минимальная поддержка неполных типов для стандартных контейнеров 201505L <forward_list> <list> <vector> (C++17)
__cpp_lib_int_pow2 Интегральные операции степени двойки (std::has_single_bit, std::bit_ceil, std::bit_floor, std::bit_length) 202002L <bit> (C++20)
__cpp_lib_integer_comparison_functions Целочисленные функции сравнения 202002L <utility> (C++20)
__cpp_lib_integer_sequence Целочисленные последовательности времени компиляции 201304L <utility> (C++14)
__cpp_lib_integral_constant_callable std::integral_constant::operator() 201304L <type_traits> (C++14)
__cpp_lib_interpolate std::lerp, std::midpoint 201902L <cmath> <numeric> (C++20)
__cpp_lib_invoke std::invoke 201411L <functional> (C++17)
__cpp_lib_invoke_r std::invoke_r 202106L <functional> (C++23)
__cpp_lib_is_aggregate std::is_aggregate 201703L <type_traits> (C++17)
__cpp_lib_is_constant_evaluated std::is_constant_evaluated 201811L <type_traits> (C++20)
__cpp_lib_is_final std::is_final 201402L <type_traits> (C++14)
__cpp_lib_is_invocable std::is_invocable, std::invoke_result 201703L <type_traits> (C++17)
__cpp_lib_is_layout_compatible std::is_layout_compatible 201907L <type_traits> (C++20)
__cpp_lib_is_nothrow_convertible std::is_nothrow_convertible 201806L <type_traits> (C++20)
__cpp_lib_is_null_pointer std::is_null_pointer 201309L <type_traits> (C++14)
__cpp_lib_is_pointer_interconvertible Свойства указателя-взаимоконвертируемости 201907L <type_traits> (C++20)
__cpp_lib_is_scoped_enum std::is_scoped_enum 202011L <type_traits> (C++23)
__cpp_lib_is_swappable [nothrow-]замена свойств 201603L <type_traits> (C++17)
__cpp_lib_jthread Стоповый токен и присоединяющаяся ветвь 201911L <stop_token> <thread> (C++20)
__cpp_lib_latch std::latch 201907L <latch> (C++20)
__cpp_lib_launder Основной Выпуск 1776: Обмен объектов класса, содержащих ссылочные элементы (std::launder) 201606L <new> (C++17)
__cpp_lib_list_remove_return_type Изменение типа возврата remove(), remove_if() и unique() элементов объектов std::forward_list и std::list 201806L <forward_list> <list> (C++20)
__cpp_lib_logical_traits Свойства типа логического оператора 201510L <type_traits> (C++17)
__cpp_lib_make_from_tuple std::make_from_tuple() 201606L <tuple> (C++17)
__cpp_lib_make_reverse_iterator std::make_reverse_iterator 201402L <iterator> (C++14)
__cpp_lib_make_unique std::make_unique 201304L <memory> (C++14)
__cpp_lib_map_try_emplace std::map::try_emplace, std::map::insert_or_assign 201411L <map> (C++17)
__cpp_lib_math_constants Математические константы 201907L <numbers> (C++20)
__cpp_lib_math_special_functions Специальные математические функции для C++17 201603L <cmath> (C++17)
__cpp_lib_memory_resource std::pmr::memory_resource 201603L <memory_resource> (C++17)
__cpp_lib_node_extract Объединение карт и наборов (std::map::extract, std::map::merge, std::map::insert(node_type) и т.д.) 201606L <map> <set> <unordered_map> <unordered_set> (C++17)
__cpp_lib_nonmember_container_access std::size(), std::data() и std::empty() 201411L <iterator> <array> <deque> <forward_list> <list> <map> <regex> <set> <string> <unordered_map> <unordered_set> <vector> (C++17)
__cpp_lib_not_fn std::not_fn() 201603L <functional> (C++17)
__cpp_lib_null_iterators Null LegacyForwardIterators 201304L <iterator> (C++14)
__cpp_lib_optional std::optional 201606L <optional> (C++17)
__cpp_lib_parallel_algorithm Параллельные алгоритмы 201603L <algorithm> <numeric> (C++17)
__cpp_lib_polymorphic_allocator std::polymorphic_allocator<> как тип словаря 201902L <memory_resource> (C++20)
__cpp_lib_quoted_string_io std::quoted 201304L <iomanip> (C++14)
__cpp_lib_ranges Библиотека диапазонов и ограниченные алгоритмы 201911L <algorithm> <functional> <iterator> <memory> <ranges> (C++20)
__cpp_lib_raw_memory_algorithms Расширение инструментов управления памятью 201606L <memory> (C++17)
__cpp_lib_remove_cvref std::remove_cvref 201711L <type_traits> (C++20)
__cpp_lib_result_of_sfinae std::result_of и SFINAE 201210L <type_traits> <functional> (C++14)
__cpp_lib_robust_nonmodifying_seq_ops Повышение устойчивости последовательности немодифицирующих операций (двухдиапазонные перегрузки для std::mismatch, std::equal и std::is_permutation) 201304L <algorithm> (C++14)
__cpp_lib_sample std::sample 201603L <algorithm> (C++17)
__cpp_lib_scoped_lock std::scoped_lock 201703L <mutex> (C++17)
__cpp_lib_semaphore std::counting_semaphore, std::binary_semaphore 201907L <semaphore> (C++20)
__cpp_lib_shared_mutex std::shared_mutex (безвременной) 201505L <shared_mutex> (C++17)
__cpp_lib_shared_ptr_arrays std::shared_ptr<T[]> 201611L <memory> (C++17)
Поддержка массива std::make_shared 201707L <memory> (C++20)
__cpp_lib_shared_ptr_weak_type shared_ptr::weak_type 201606L <memory> (C++17)
__cpp_lib_shared_timed_mutex std::shared_timed_mutex 201402L <shared_mutex> (C++14)
__cpp_lib_shift std::shift_left и std::shift_right 201806L <algorithm> (C++20)
__cpp_lib_smart_ptr_for_overwrite Создание умного указателя с инициализацией по умолчанию (std::allocate_shared_for_overwrite, std::make_shared_for_overwrite, std::make_unique_for_overwrite) 202002L <memory> (C++20)
__cpp_lib_source_location Сбор информации об исходном коде (std::source_location) 201907L <source_location> (C++20)
__cpp_lib_span std::span 202002L <span> (C++20)
__cpp_lib_ssize std::ssize и беззнаковый std::span::size 201902L <iterator> (C++20)
__cpp_lib_stacktrace Библиотека Stacktrace 202011L <stacktrace> (C++23)
__cpp_lib_starts_ends_with Проверка префикса и суффикса строки (starts_with() и ends_with() для std::string и std::string_view) 201711L <string> <string_view> (C++20)
__cpp_lib_stdatomic_h Заголовок совместимости для атомарных операций C 202011L <stdatomic.h> (C++23)
__cpp_lib_string_contains Функции contains объектов std::basic_string и std::basic_string_view 202011L <string> <string_view> (C++23)
__cpp_lib_string_udls Пользовательские литералы для строковых типов 201304L <string> (C++14)
__cpp_lib_string_view std::string_view 201606L <string> <string_view> (C++17)
ConstexprIterator 201803L <string> <string_view> (C++20)
__cpp_lib_syncbuf Синхронизированный буферизированный ostream (std::syncbuf, std::osyncstream) и манипуляторы 201803L <syncstream> (C++20)
__cpp_lib_three_way_comparison Трёхстороннее сравнение (поддержка библиотекой); добавление трёхстороннего сравнения в библиотеку 201907L <compare> (C++20)
__cpp_lib_to_address Утилита для преобразования указателя в сырой указатель (std::to_address) 201711L <memory> (C++20)
__cpp_lib_to_array std::to_array 201907L <array> (C++20)
__cpp_lib_to_chars Элементарные преобразования строк (std::to_chars, std::from_chars) 201611L <charconv> (C++17)
__cpp_lib_to_underlying std::to_underlying 2XXXXXL <utility> (C++23)
__cpp_lib_transformation_trait_aliases Шаблоны псевдонимов для TransformationTraits 201304L <type_traits> (C++14)
__cpp_lib_transparent_operators Прозрачные операторы функторы (std::less<> и другие) 201210L <functional> (C++14)
Прозрачный std::owner_less (std::owner_less<void>) 201510L <memory> <functional> (C++17)
__cpp_lib_tuple_element_t std::tuple_element_t 201402L <tuple> (C++14)
__cpp_lib_tuples_by_type Адресация кортежей по типу 201304L <tuple> <utility> (C++14)
__cpp_lib_type_identity std::type_identity 201806L <type_traits> (C++20)
__cpp_lib_type_trait_variable_templates Шаблоны переменных свойств типов (std::is_void_v, etc) 201510L <type_traits> (C++17)
__cpp_lib_uncaught_exceptions std::uncaught_exceptions 201411L <exception> (C++17)
__cpp_lib_unordered_map_try_emplace std::unordered_map::try_emplace, std::unordered_map::insert_or_assign 201411L <unordered_map> (C++17)
__cpp_lib_unwrap_ref std::unwrap_ref_decay и std::unwrap_reference 201811L <functional> (C++20)
__cpp_lib_variant std::variant: типобезопасное объединение для C++17 201606L <variant> (C++17)
__cpp_lib_void_t std::void_t 201411L <type_traits> (C++17)

[править] Пример

[править] Обычное использование

#ifdef __has_include                           // Проверяет, присутствует ли __has_include
#  if __has_include(<optional>)                // Проверяет наличие стандартной библиотеки
#    include <optional>
#  elif __has_include(<experimental/optional>) // Проверяет наличие экспериментальной
                                               // версии
#    include <experimental/optional>
#  elif __has_include(<boost/optional.hpp>)    // Проверяет наличие внешней библиотеки
#    include <boost/optional.hpp>
#  else                                        // Вообще ничего не найдено
#     error "Отсутствует <optional>"
#  endif
#endif
 
#ifdef __has_cpp_attribute                      // Проверяет, присутствует ли
                                                // __has_cpp_attribute
#  if __has_cpp_attribute(deprecated)           // Проверяет атрибут
#    define DEPRECATED(msg) [[deprecated(msg)]]
#  endif
#endif
#ifndef DEPRECATED
#    define DEPRECATED(msg)
#endif
 
DEPRECATED("foo() устарела") void foo();
 
#if __cpp_constexpr >= 201304                   // Проверяет конкретную версию
                                                // функциональности
#  define CONSTEXPR constexpr
#else
#  define CONSTEXPR inline
#endif
 
CONSTEXPR int bar(unsigned i)
{
#if __cpp_binary_literals                    // Проверяет наличие функциональности
    unsigned mask1 = 0b11000000;
    unsigned mask2 = 0b00000111;
#else
    unsigned mask1 = 0xC0;
    unsigned mask2 = 0x07;
#endif
    if ( i & mask1 )
        return 1;
    if ( i & mask2 )
        return 2;
    return 0;
}
 
int main()
{
}

[править] Дамп возможностей компилятора

Следующая (совместимая с C++11) программа выводит функциональность и атрибуты компилятора C++.

// Измените эти параметры, чтобы распечатать только необходимую информацию.
static struct PrintOptions {
    constexpr static int longest_macro_name { 45 };
    constexpr static bool titles               = 1;
    constexpr static bool counters             = 1;
    constexpr static bool attributes           = 1;
    constexpr static bool standard_values      = 1;
    constexpr static bool compiler_specific    = 1;
    constexpr static bool core_features        = 1;
    constexpr static bool lib_features         = 1;
    constexpr static bool supported_features   = 1;
    constexpr static bool unsupported_features = 1;
    constexpr static bool sort_by_date         = 0;
    constexpr static bool separate_year_month  = 1;
    constexpr static bool separated_revisions  = 1;
    constexpr static bool latest_revisions     = 1;
    constexpr static bool cxx98                = 0;
    constexpr static bool cxx11                = 1;
    constexpr static bool cxx14                = 1;
    constexpr static bool cxx17                = 1;
    constexpr static bool cxx20                = 1;
    constexpr static bool cxx23                = 1;
    constexpr static bool cxx26                = 1;
    constexpr static bool cxx29                = 0;
}   print;
 
#if __cplusplus < 201100
#  error "Требуется C++11 или выше"
#endif
 
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <utility>
#include <vector>
 
#ifdef __has_include
# if __has_include(<version>)
#   include <version>
# endif
#endif
 
// Ожидает строку, которая начинается с 6 десятичных цифр или с '_'
// (если не поддерживается)
#define COMPILER_VALUE_INT(n) #n [0] == '_' ? 0 : \
    (#n[5] - '0') + (#n[4] - '0') * 10 + (#n[3] - '0') * 100 + \
    (#n[2] - '0') * 1000 + (#n[1] - '0') * 10000 + (#n[0] - '0') * 100000
#define COMPILER_FEATURE_ENTRY(expect, name) { #name, COMPILER_VALUE_INT(name), expect },
 
#ifdef __has_cpp_attribute
# define COMPILER_ATTRIBUTE(expect, name) { #name, __has_cpp_attribute(name), expect },
#else
# define COMPILER_ATTRIBUTE(expect, name) { #name, COMPILER_VALUE_INT(name), expect },
#endif
 
#define COMPILER_SPECIFIC_STRING(value) #value
#define COMPILER_SPECIFIC_ENTRY(name) { #name, COMPILER_SPECIFIC_STRING(name) },
 
class CompilerFeature
{
    char const* name_; long data_; long std_;
public:
    constexpr CompilerFeature(char const* name, long data, long std)
        : name_(name), data_(data), std_(std) {}
    constexpr CompilerFeature(CompilerFeature const&) = default;
    CompilerFeature& operator=(CompilerFeature const&) = default;
    bool operator<(CompilerFeature const& rhs) const
        { return std::strcmp(name_, rhs.name_) < 0; }
    bool operator==(CompilerFeature const& rhs) const
        { return std::strcmp(name_, rhs.name_) == 0; }
    constexpr bool supported() const { return data_ >= std_; }
    constexpr bool maybe() const { return data_ > 0; }
    constexpr char const* name() const { return name_; }
    constexpr long std() const { return std_; }
    constexpr long data() const { return data_; }
    void data(long x) { data_ = x; }
};
 
static /*constexpr*/ std::pair<const char*, const char*> compiler[] = {
    COMPILER_SPECIFIC_ENTRY(__cplusplus) //< не зависит от компилятора, но полезен :)
    COMPILER_SPECIFIC_ENTRY(__clang_major__)
    COMPILER_SPECIFIC_ENTRY(__clang_minor__)
    COMPILER_SPECIFIC_ENTRY(__clang_patchlevel__)
    COMPILER_SPECIFIC_ENTRY(__GNUG__)
    COMPILER_SPECIFIC_ENTRY(__GNUC_MINOR__)
    COMPILER_SPECIFIC_ENTRY(__GNUC_PATCHLEVEL__)
    // Добавьте свои любимые макросы для компилятора. Неопределённые не будут напечатаны.
};
 
static constexpr CompilerFeature cxx98_core[] = {
    COMPILER_FEATURE_ENTRY(199711L, __cpp_exceptions)
    COMPILER_FEATURE_ENTRY(199711L, __cpp_rtti)
};
 
static constexpr CompilerFeature cxx11_core[] = {
    COMPILER_FEATURE_ENTRY(200704L, __cpp_alias_templates)
    COMPILER_FEATURE_ENTRY(200809L, __cpp_attributes)
    COMPILER_FEATURE_ENTRY(200704L, __cpp_constexpr)
    COMPILER_FEATURE_ENTRY(201711L, __cpp_constexpr_in_decltype)
    COMPILER_FEATURE_ENTRY(200707L, __cpp_decltype)
    COMPILER_FEATURE_ENTRY(200604L, __cpp_delegating_constructors)
    COMPILER_FEATURE_ENTRY(201511L, __cpp_inheriting_constructors)
    COMPILER_FEATURE_ENTRY(200806L, __cpp_initializer_lists)
    COMPILER_FEATURE_ENTRY(200907L, __cpp_lambdas)
    COMPILER_FEATURE_ENTRY(200809L, __cpp_nsdmi)
    COMPILER_FEATURE_ENTRY(200907L, __cpp_range_based_for)
    COMPILER_FEATURE_ENTRY(200710L, __cpp_raw_strings)
    COMPILER_FEATURE_ENTRY(200710L, __cpp_ref_qualifiers)
    COMPILER_FEATURE_ENTRY(200610L, __cpp_rvalue_references)
    COMPILER_FEATURE_ENTRY(200410L, __cpp_static_assert)
    COMPILER_FEATURE_ENTRY(200806L, __cpp_threadsafe_static_init)
    COMPILER_FEATURE_ENTRY(200704L, __cpp_unicode_characters)
    COMPILER_FEATURE_ENTRY(200710L, __cpp_unicode_literals)
    COMPILER_FEATURE_ENTRY(200809L, __cpp_user_defined_literals)
    COMPILER_FEATURE_ENTRY(200704L, __cpp_variadic_templates)
};
 
static constexpr CompilerFeature cxx14_core[] = {
    COMPILER_FEATURE_ENTRY(201304L, __cpp_aggregate_nsdmi)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_binary_literals)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_constexpr)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_decltype_auto)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_generic_lambdas)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_init_captures)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_return_type_deduction)
    COMPILER_FEATURE_ENTRY(201309L, __cpp_sized_deallocation)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_variable_templates)
};
static constexpr CompilerFeature cxx14_lib[] = {
    COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_chrono_udls)
    COMPILER_FEATURE_ENTRY(201309L, __cpp_lib_complex_udls)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_exchange_function)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_generic_associative_lookup)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_integer_sequence)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_integral_constant_callable)
    COMPILER_FEATURE_ENTRY(201402L, __cpp_lib_is_final)
    COMPILER_FEATURE_ENTRY(201309L, __cpp_lib_is_null_pointer)
    COMPILER_FEATURE_ENTRY(201402L, __cpp_lib_make_reverse_iterator)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_make_unique)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_null_iterators)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_quoted_string_io)
    COMPILER_FEATURE_ENTRY(201210L, __cpp_lib_result_of_sfinae)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_robust_nonmodifying_seq_ops)
    COMPILER_FEATURE_ENTRY(201402L, __cpp_lib_shared_timed_mutex)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_string_udls)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_transformation_trait_aliases)
    COMPILER_FEATURE_ENTRY(201210L, __cpp_lib_transparent_operators)
    COMPILER_FEATURE_ENTRY(201402L, __cpp_lib_tuple_element_t)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_tuples_by_type)
};
 
static constexpr CompilerFeature cxx17_core[] = {
    COMPILER_FEATURE_ENTRY(201603L, __cpp_aggregate_bases)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_aligned_new)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_capture_star_this)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_constexpr)
    COMPILER_FEATURE_ENTRY(201703L, __cpp_deduction_guides)
    COMPILER_FEATURE_ENTRY(201411L, __cpp_enumerator_attributes)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_fold_expressions)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_guaranteed_copy_elision)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_hex_float)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_if_constexpr)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_inline_variables)
    COMPILER_FEATURE_ENTRY(201411L, __cpp_namespace_attributes)
    COMPILER_FEATURE_ENTRY(201510L, __cpp_noexcept_function_type)
    COMPILER_FEATURE_ENTRY(201411L, __cpp_nontype_template_args)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_nontype_template_parameter_auto)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_range_based_for)
    COMPILER_FEATURE_ENTRY(201411L, __cpp_static_assert)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_structured_bindings)
    COMPILER_FEATURE_ENTRY(201611L, __cpp_template_template_args)
    COMPILER_FEATURE_ENTRY(201611L, __cpp_variadic_using)
};
static constexpr CompilerFeature cxx17_lib[] = {
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_addressof_constexpr)
    COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_allocator_traits_is_always_equal)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_any)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_apply)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_array_constexpr)
    COMPILER_FEATURE_ENTRY(201510L, __cpp_lib_as_const)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_atomic_is_always_lock_free)
    COMPILER_FEATURE_ENTRY(201505L, __cpp_lib_bool_constant)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_boyer_moore_searcher)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_byte)
    COMPILER_FEATURE_ENTRY(201611L, __cpp_lib_chrono)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_clamp)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_enable_shared_from_this)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_execution)
    COMPILER_FEATURE_ENTRY(201703L, __cpp_lib_filesystem)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_gcd_lcm)
    COMPILER_FEATURE_ENTRY(201703L, __cpp_lib_hardware_interference_size)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_has_unique_object_representations)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_hypot)
    COMPILER_FEATURE_ENTRY(201505L, __cpp_lib_incomplete_container_elements)
    COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_invoke)
    COMPILER_FEATURE_ENTRY(201703L, __cpp_lib_is_aggregate)
    COMPILER_FEATURE_ENTRY(201703L, __cpp_lib_is_invocable)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_is_swappable)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_launder)
    COMPILER_FEATURE_ENTRY(201510L, __cpp_lib_logical_traits)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_make_from_tuple)
    COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_map_try_emplace)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_math_special_functions)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_memory_resource)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_node_extract)
    COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_nonmember_container_access)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_not_fn)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_optional)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_parallel_algorithm)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_raw_memory_algorithms)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_sample)
    COMPILER_FEATURE_ENTRY(201703L, __cpp_lib_scoped_lock)
    COMPILER_FEATURE_ENTRY(201505L, __cpp_lib_shared_mutex)
    COMPILER_FEATURE_ENTRY(201611L, __cpp_lib_shared_ptr_arrays)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_shared_ptr_weak_type)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_string_view)
    COMPILER_FEATURE_ENTRY(201611L, __cpp_lib_to_chars)
    COMPILER_FEATURE_ENTRY(201510L, __cpp_lib_transparent_operators)
    COMPILER_FEATURE_ENTRY(201510L, __cpp_lib_type_trait_variable_templates)
    COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_uncaught_exceptions)
    COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_unordered_map_try_emplace)
    COMPILER_FEATURE_ENTRY(202102L, __cpp_lib_variant)
    COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_void_t)
};
 
static constexpr CompilerFeature cxx20_core[] = {
    COMPILER_FEATURE_ENTRY(201902L, __cpp_aggregate_paren_init)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_char8_t)
    COMPILER_FEATURE_ENTRY(202002L, __cpp_concepts)
    COMPILER_FEATURE_ENTRY(201806L, __cpp_conditional_explicit)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_consteval)
    COMPILER_FEATURE_ENTRY(202002L, __cpp_constexpr)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_constexpr_dynamic_alloc)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_constinit)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_deduction_guides)
    COMPILER_FEATURE_ENTRY(201707L, __cpp_designated_initializers)
    COMPILER_FEATURE_ENTRY(201707L, __cpp_generic_lambdas)
    COMPILER_FEATURE_ENTRY(201902L, __cpp_impl_coroutine)
    COMPILER_FEATURE_ENTRY(201806L, __cpp_impl_destroying_delete)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_impl_three_way_comparison)
    COMPILER_FEATURE_ENTRY(201803L, __cpp_init_captures)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_modules)
    COMPILER_FEATURE_ENTRY(201911L, __cpp_nontype_template_args)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_using_enum)
};
static constexpr CompilerFeature cxx20_lib[] = {
    COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_array_constexpr)
    COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_assume_aligned)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_atomic_flag_test)
    COMPILER_FEATURE_ENTRY(201711L, __cpp_lib_atomic_float)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_atomic_lock_free_type_aliases)
    COMPILER_FEATURE_ENTRY(201806L, __cpp_lib_atomic_ref)
    COMPILER_FEATURE_ENTRY(201711L, __cpp_lib_atomic_shared_ptr)
    COMPILER_FEATURE_ENTRY(201911L, __cpp_lib_atomic_value_initialization)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_atomic_wait)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_barrier)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_bind_front)
    COMPILER_FEATURE_ENTRY(201806L, __cpp_lib_bit_cast)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_bitops)
    COMPILER_FEATURE_ENTRY(201902L, __cpp_lib_bounded_array_traits)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_char8_t)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_chrono)
    COMPILER_FEATURE_ENTRY(202002L, __cpp_lib_concepts)
    COMPILER_FEATURE_ENTRY(201806L, __cpp_lib_constexpr_algorithms)
    COMPILER_FEATURE_ENTRY(201711L, __cpp_lib_constexpr_complex)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_constexpr_dynamic_alloc)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_constexpr_functional)
    COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_constexpr_iterator)
    COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_constexpr_memory)
    COMPILER_FEATURE_ENTRY(201911L, __cpp_lib_constexpr_numeric)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_constexpr_string)
    COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_constexpr_string_view)
    COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_constexpr_tuple)
    COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_constexpr_utility)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_constexpr_vector)
    COMPILER_FEATURE_ENTRY(201902L, __cpp_lib_coroutine)
    COMPILER_FEATURE_ENTRY(201806L, __cpp_lib_destroying_delete)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_endian)
    COMPILER_FEATURE_ENTRY(202002L, __cpp_lib_erase_if)
    COMPILER_FEATURE_ENTRY(201902L, __cpp_lib_execution)
    COMPILER_FEATURE_ENTRY(202110L, __cpp_lib_format)
    COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_generic_unordered_lookup)
    COMPILER_FEATURE_ENTRY(202002L, __cpp_lib_int_pow2)
    COMPILER_FEATURE_ENTRY(202002L, __cpp_lib_integer_comparison_functions)
    COMPILER_FEATURE_ENTRY(201902L, __cpp_lib_interpolate)
    COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_is_constant_evaluated)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_is_layout_compatible)
    COMPILER_FEATURE_ENTRY(201806L, __cpp_lib_is_nothrow_convertible)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_is_pointer_interconvertible)
    COMPILER_FEATURE_ENTRY(201911L, __cpp_lib_jthread)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_latch)
    COMPILER_FEATURE_ENTRY(201806L, __cpp_lib_list_remove_return_type)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_math_constants)
    COMPILER_FEATURE_ENTRY(202106L, __cpp_lib_optional)
    COMPILER_FEATURE_ENTRY(201902L, __cpp_lib_polymorphic_allocator)
    COMPILER_FEATURE_ENTRY(202110L, __cpp_lib_ranges)
    COMPILER_FEATURE_ENTRY(201711L, __cpp_lib_remove_cvref)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_semaphore)
    COMPILER_FEATURE_ENTRY(201707L, __cpp_lib_shared_ptr_arrays)
    COMPILER_FEATURE_ENTRY(201806L, __cpp_lib_shift)
    COMPILER_FEATURE_ENTRY(202002L, __cpp_lib_smart_ptr_for_overwrite)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_source_location)
    COMPILER_FEATURE_ENTRY(202002L, __cpp_lib_span)
    COMPILER_FEATURE_ENTRY(201902L, __cpp_lib_ssize)
    COMPILER_FEATURE_ENTRY(201711L, __cpp_lib_starts_ends_with)
    COMPILER_FEATURE_ENTRY(201803L, __cpp_lib_string_view)
    COMPILER_FEATURE_ENTRY(201803L, __cpp_lib_syncbuf)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_three_way_comparison)
    COMPILER_FEATURE_ENTRY(201711L, __cpp_lib_to_address)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_to_array)
    COMPILER_FEATURE_ENTRY(201806L, __cpp_lib_type_identity)
    COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_unwrap_ref)
    COMPILER_FEATURE_ENTRY(202106L, __cpp_lib_variant)
};
 
static constexpr CompilerFeature cxx23_core[] = {
    COMPILER_FEATURE_ENTRY(202110L, __cpp_auto_cast)
    COMPILER_FEATURE_ENTRY(202211L, __cpp_constexpr)
    COMPILER_FEATURE_ENTRY(202110L, __cpp_explicit_this_parameter)
    COMPILER_FEATURE_ENTRY(202106L, __cpp_if_consteval)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_implicit_move)
    COMPILER_FEATURE_ENTRY(202211L, __cpp_multidimensional_subscript)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_named_character_escapes)
    COMPILER_FEATURE_ENTRY(202211L, __cpp_range_based_for)
    COMPILER_FEATURE_ENTRY(202011L, __cpp_size_t_suffix)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_static_call_operator)
};
static constexpr CompilerFeature cxx23_lib[] = {
    COMPILER_FEATURE_ENTRY(202106L, __cpp_lib_adaptor_iterator_pair_constructor)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_algorithm_iterator_requirements)
    COMPILER_FEATURE_ENTRY(202302L, __cpp_lib_allocate_at_least)
    COMPILER_FEATURE_ENTRY(202110L, __cpp_lib_associative_heterogeneous_erasure)
    COMPILER_FEATURE_ENTRY(202302L, __cpp_lib_barrier)
    COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_bind_back)
    COMPILER_FEATURE_ENTRY(202110L, __cpp_lib_byteswap)
    COMPILER_FEATURE_ENTRY(202302L, __cpp_lib_common_reference)
    COMPILER_FEATURE_ENTRY(202302L, __cpp_lib_common_reference_wrapper)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_concepts)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_constexpr_bitset)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_constexpr_charconv)
    COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_constexpr_cmath)
    COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_constexpr_memory)
    COMPILER_FEATURE_ENTRY(202106L, __cpp_lib_constexpr_typeinfo)
    COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_containers_ranges)
    COMPILER_FEATURE_ENTRY(202211L, __cpp_lib_expected)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_flat_map)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_flat_set)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_format)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_format_ranges)
    COMPILER_FEATURE_ENTRY(202302L, __cpp_lib_formatters)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_forward_like)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_generator)
    COMPILER_FEATURE_ENTRY(202106L, __cpp_lib_invoke_r)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ios_noreplace)
    COMPILER_FEATURE_ENTRY(202302L, __cpp_lib_is_implicit_lifetime)
    COMPILER_FEATURE_ENTRY(202011L, __cpp_lib_is_scoped_enum)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_mdspan)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_modules)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_move_iterator_concept)
    COMPILER_FEATURE_ENTRY(202110L, __cpp_lib_move_only_function)
    COMPILER_FEATURE_ENTRY(202110L, __cpp_lib_optional)
    COMPILER_FEATURE_ENTRY(202106L, __cpp_lib_out_ptr)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_print)
    COMPILER_FEATURE_ENTRY(202302L, __cpp_lib_ranges)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ranges_as_const)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ranges_as_rvalue)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ranges_cartesian_product)
    COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_ranges_chunk)
    COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_ranges_chunk_by)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ranges_contains)
    COMPILER_FEATURE_ENTRY(202302L, __cpp_lib_ranges_enumerate)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ranges_find_last)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ranges_fold)
    COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_ranges_iota)
    COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_ranges_join_with)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ranges_repeat)
    COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_ranges_slide)
    COMPILER_FEATURE_ENTRY(202106L, __cpp_lib_ranges_starts_ends_with)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ranges_stride)
    COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_ranges_to_container)
    COMPILER_FEATURE_ENTRY(202110L, __cpp_lib_ranges_zip)
    COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_reference_from_temporary)
    COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_shift)
    COMPILER_FEATURE_ENTRY(202106L, __cpp_lib_spanstream)
    COMPILER_FEATURE_ENTRY(202011L, __cpp_lib_stacktrace)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_start_lifetime_as)
    COMPILER_FEATURE_ENTRY(202011L, __cpp_lib_stdatomic_h)
    COMPILER_FEATURE_ENTRY(202011L, __cpp_lib_string_contains)
    COMPILER_FEATURE_ENTRY(202110L, __cpp_lib_string_resize_and_overwrite)
    COMPILER_FEATURE_ENTRY(202102L, __cpp_lib_to_underlying)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_tuple_like)
    COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_unreachable)
};
 
static constexpr CompilerFeature cxx26_core[] = {
    //< Продолжить заполнение
    COMPILER_FEATURE_ENTRY(202306L, __cpp_constexpr)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_placeholder_variables)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_static_assert)
};
static constexpr CompilerFeature cxx26_lib[] = {
    //< Продолжить заполнение
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_associative_heterogeneous_insertion)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_bind_back)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_bind_front)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_bitset)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_chrono)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_constexpr_algorithms)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_constexpr_cmath)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_constexpr_complex)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_copyable_function)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_format)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_char_traits)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_charconv)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_cstdlib)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_cstring)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_cwchar)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_errc)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_feature_test_macros)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_functional)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_iterator)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_memory)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_operator_new)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_ranges)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_ratio)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_tuple)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_freestanding_utility)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_fstream_native_handle)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_function_ref)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_hazard_pointer)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_is_within_lifetime)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_not_fn)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_ratio)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_rcu)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_smart_ptr_owner_equality)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_sstream_from_string_view)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_submdspan)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_text_encoding)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_to_chars)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_to_string)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_variant)
};
 
static constexpr CompilerFeature cxx29_core[] = {
    //< Продолжить заполнение
    COMPILER_FEATURE_ENTRY(202604L, __cpp_core_TODO)
};
static constexpr CompilerFeature cxx29_lib[] = {
    //< Продолжить заполнение
    COMPILER_FEATURE_ENTRY(202604L, __cpp_lib_TODO)
};
 
static constexpr CompilerFeature attributes[] = {
    COMPILER_ATTRIBUTE(202207L, assume)
    COMPILER_ATTRIBUTE(200809L, carries_dependency)
    COMPILER_ATTRIBUTE(201309L, deprecated)
    COMPILER_ATTRIBUTE(201603L, fallthrough)
    COMPILER_ATTRIBUTE(201803L, likely)
    COMPILER_ATTRIBUTE(201603L, maybe_unused)
    COMPILER_ATTRIBUTE(201803L, no_unique_address)
    COMPILER_ATTRIBUTE(201907L, nodiscard)
    COMPILER_ATTRIBUTE(200809L, noreturn)
    COMPILER_ATTRIBUTE(201803L, unlikely)
};
 
inline void show_compiler_specific_info()
{
    std::printf("Макросы, специфичные для компилятора:\n");
    for (auto co : compiler)
        if (std::strcmp(co.first, co.second))
            std::printf("%*s %s\n", -print.longest_macro_name, co.first, co.second);
}
 
inline void print_compiler_feature(const CompilerFeature& x)
{
    if (not ((print.supported_features and x.maybe()) or
            (print.unsupported_features and not x.maybe())))
        return;
    auto print_year_month = [](long n)
    {
        return std::printf("%ld%s%02ld",
            n / 100, print.separate_year_month ? "-" : "", n % 100);
    };
    std::printf("%*s ", -print.longest_macro_name, x.name());
    x.maybe() ? print_year_month(x.data()) :
                    std::printf("------%s", print.separate_year_month ? "-" : "");
    if (print.standard_values)
        std::printf("  %c  ", (x.supported() ? (x.data() > x.std() ? '>' : '=') : '<')),
            print_year_month(x.std());
    std::puts("");
}
 
template<class Container>
inline void show(char const* const title, Container const& co)
{
    if (print.titles)
    {
        std::printf("%-s (", title);
        if (print.counters)
        {
            std::printf("%ld/", std::count_if(std::begin(co), std::end(co),
                [](CompilerFeature x)
                {
                    return x.supported();
                }));
        }
        std::printf("%td)\n", std::distance(std::begin(co), std::end(co)));
    }
    if (print.sort_by_date)
    {
        std::vector<CompilerFeature> v(std::begin(co), std::end(co));
        std::stable_sort(v.begin(), v.end(),
            [](CompilerFeature const& lhs, CompilerFeature const& rhs)
            {
                return lhs.data() < rhs.data();
            });
        std::for_each(v.cbegin(), v.cend(), print_compiler_feature);
    }
    else
        std::for_each(std::begin(co), std::end(co), print_compiler_feature);
    std::puts("");
}
 
inline void show_latest()
{
    auto latest_rev = []() -> int
    {
        return print.cxx29 ? 29 : print.cxx26 ? 26 : print.cxx23 ? 23 : print.cxx20 ? 20 :
               print.cxx17 ? 17 : print.cxx14 ? 14 : print.cxx11 ? 11 : 98;
    };
    std::vector<CompilerFeature> latest;
    auto add = [&latest](CompilerFeature x)
    {
        auto i = std::lower_bound(latest.begin(), latest.end(), x);
        if (i == latest.end() or not (*i == x))
            latest.insert(i, x);
        else if (i->data() < x.data())
            i->data(x.data());
    };
    char text[64];
    latest.reserve(512); // макросы max
    if (print.core_features)
    {   // сохранить обратный порядок вставки ревизии!
        if (print.cxx29) std::for_each(std::begin(cxx29_core), std::end(cxx29_core), add);
        if (print.cxx26) std::for_each(std::begin(cxx26_core), std::end(cxx26_core), add);
        if (print.cxx23) std::for_each(std::begin(cxx23_core), std::end(cxx23_core), add);
        if (print.cxx20) std::for_each(std::begin(cxx20_core), std::end(cxx20_core), add);
        if (print.cxx17) std::for_each(std::begin(cxx17_core), std::end(cxx17_core), add);
        if (print.cxx14) std::for_each(std::begin(cxx14_core), std::end(cxx14_core), add);
        if (print.cxx11) std::for_each(std::begin(cxx11_core), std::end(cxx11_core), add);
        if (print.cxx98) std::for_each(std::begin(cxx98_core), std::end(cxx98_core), add);
        std::snprintf(text, sizeof text, "ВСЕ МАКРОСЫ CORE ДО C++%02i", latest_rev());
        show(text, latest);
    }
    latest.clear();
    if (print.lib_features)
    {   // сохранить обратный порядок вставки ревизии!
        if (print.cxx29) std::for_each(std::begin(cxx29_lib), std::end(cxx29_lib), add);
        if (print.cxx26) std::for_each(std::begin(cxx26_lib), std::end(cxx26_lib), add);
        if (print.cxx23) std::for_each(std::begin(cxx23_lib), std::end(cxx23_lib), add);
        if (print.cxx20) std::for_each(std::begin(cxx20_lib), std::end(cxx20_lib), add);
        if (print.cxx17) std::for_each(std::begin(cxx17_lib), std::end(cxx17_lib), add);
        if (print.cxx14) std::for_each(std::begin(cxx14_lib), std::end(cxx14_lib), add);
        std::snprintf(text, sizeof text, "ВСЕ МАКРОСЫ LIB ДО C++%02i", latest_rev());
        show(text, latest);
    }
}
 
int main()
{
    if (print.separated_revisions)
    {
        if (print.cxx98 and print.core_features) show("C++98 CORE", cxx98_core);
        if (print.cxx11 and print.core_features) show("C++11 CORE", cxx11_core);
        if (print.cxx14 and print.core_features) show("C++14 CORE", cxx14_core);
        if (print.cxx14 and print.lib_features ) show("C++14 LIB" , cxx14_lib);
        if (print.cxx17 and print.core_features) show("C++17 CORE", cxx17_core);
        if (print.cxx17 and print.lib_features ) show("C++17 LIB" , cxx17_lib);
        if (print.cxx20 and print.core_features) show("C++20 CORE", cxx20_core);
        if (print.cxx20 and print.lib_features ) show("C++20 LIB" , cxx20_lib);
        if (print.cxx23 and print.core_features) show("C++23 CORE", cxx23_core);
        if (print.cxx23 and print.lib_features ) show("C++23 LIB" , cxx23_lib);
        if (print.cxx26 and print.core_features) show("C++26 CORE", cxx26_core);
        if (print.cxx26 and print.lib_features ) show("C++26 LIB" , cxx26_lib);
        if (print.cxx29 and print.core_features) show("C++29 CORE", cxx29_core);
        if (print.cxx29 and print.lib_features ) show("C++29 LIB" , cxx29_lib);
    }
    if (print.latest_revisions) show_latest();
    if (print.attributes) show("АТРИБУТЫ", attributes);
    if (print.compiler_specific) show_compiler_specific_info();
}

Возможный вывод:

C++11 CORE (20/20)
__cpp_alias_templates                        2007-04  =  2007-04
__cpp_attributes                             2008-09  =  2008-09
__cpp_constexpr                              2021-10  >  2007-04
__cpp_constexpr_in_decltype                  2017-11  =  2017-11
... усечено ...
 
C++14 CORE (9/9)
__cpp_aggregate_nsdmi                        2013-04  =  2013-04
__cpp_binary_literals                        2013-04  =  2013-04
__cpp_constexpr                              2021-10  >  2013-04
... усечено ...
 
C++14 LIB (20/20)
__cpp_lib_chrono_udls                        2013-04  =  2013-04
__cpp_lib_complex_udls                       2013-09  =  2013-09
__cpp_lib_exchange_function                  2013-04  =  2013-04
... усечено ...
 
C++17 CORE (20/20)
__cpp_aggregate_bases                        2016-03  =  2016-03
__cpp_aligned_new                            2016-06  =  2016-06
__cpp_capture_star_this                      2016-03  =  2016-03
__cpp_constexpr                              2021-10  >  2016-03
... усечено ...
 
C++17 LIB (49/49)
__cpp_lib_addressof_constexpr                2016-03  =  2016-03
__cpp_lib_allocator_traits_is_always_equal   2014-11  =  2014-11
... усечено ...
 
C++20 CORE (17/18)
__cpp_aggregate_paren_init                   2019-02  =  2019-02
__cpp_char8_t                                2018-11  =  2018-11
__cpp_concepts                               2020-02  =  2020-02
... усечено ...
 
C++20 LIB (64/67)
__cpp_lib_array_constexpr                    2018-11  =  2018-11
__cpp_lib_assume_aligned                     2018-11  =  2018-11
__cpp_lib_atomic_flag_test                   2019-07  =  2019-07
... усечено ...
 
C++23 CORE (2/11)
__cpp_char8_t                                2018-11  <  2022-07
__cpp_consteval                              2018-11  <  2022-11
... усечено ...
 
C++23 LIB (16/64)
__cpp_lib_adaptor_iterator_pair_constructor  2021-06  =  2021-06
__cpp_lib_algorithm_iterator_requirements    -------  <  2022-07
__cpp_lib_allocate_at_least                  -------  <  2023-02
__cpp_lib_associative_heterogeneous_erasure  -------  <  2021-10
__cpp_lib_barrier                            2019-07  <  2023-02
... усечено ...
 
ВСЕ МАКРОСЫ CORE ДО C++23 (55/65)
__cpp_aggregate_bases                        2016-03  =  2016-03
__cpp_aggregate_nsdmi                        2013-04  =  2013-04
__cpp_aggregate_paren_init                   2019-02  =  2019-02
__cpp_alias_templates                        2007-04  =  2007-04
... усечено ...
 
ВСЕ МАКРОСЫ LIB ДО C++23 (135/185)
__cpp_lib_adaptor_iterator_pair_constructor  2021-06  =  2021-06
__cpp_lib_addressof_constexpr                2016-03  =  2016-03
__cpp_lib_algorithm_iterator_requirements    -------  <  2022-07
__cpp_lib_allocate_at_least                  -------  <  2023-02
__cpp_lib_allocator_traits_is_always_equal   2014-11  =  2014-11
... усечено ...
 
АТРИБУТЫ (8/10)
assume                                       -------  <  2022-07
carries_dependency                           -------  <  2008-09
deprecated                                   2013-09  =  2013-09
fallthrough                                  2016-03  =  2016-03
... усечено ...
 
Compiler specific macros:
__cplusplus                                  202100L
__GNUG__                                     12
__GNUC_MINOR__                               2
__GNUC_PATCHLEVEL__                          1

[править] Отчёты о дефектах

Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:

Номер Применён Поведение в стандарте Корректное поведение
WG не указан C++20 для стандартных атрибутов __has_cpp_attribute
должен расширяться до ненулевого значения
может расширяться до 0

[править] Смотрите также

Макросы тестирования функциональности библиотеки (C++20) определено в заголовке <version>
Документация C++ по Предопределенные символы макросов
Документация C++ по Индекс макросимволов

[править] Внешние ссылки

1.  Официальный документ о рекомендациях по тестированию функциональности
2.  Исходный код для дампа функциональности компилятора