Namespaces
Variants
Views
Actions

Feature testing (C++20)

From cppreference.com
< cpp

The standard defines a set of preprocessor macros corresponding to C++ language and library features introduced in C++11 or later. They are intended as a simple and portable way to detect the presence of said features.

Contents

[edit] Attributes

__has_cpp_attribute( attribute-token )

Checks for the presence of an attribute named by attribute-token (after macro expansion).

For standard attributes, it will expand to the year and month in which the attribute was added to the working draft (see table below), the presence of vendor-specific attributes is determined by a non-zero value.

__has_cpp_attribute can be expanded in the expression of #if and #elif. It is treated as a defined macro by #ifdef, #ifndef and defined but cannot be used anywhere else.

attribute-token Attribute Value Standard
carries_dependency [[carries_dependency]] 200809L (C++11)
deprecated [[deprecated]] 201309L (C++14)
fallthrough [[fallthrough]] 201603L (C++17)
likely [[likely]] 201803L (C++20)
maybe_unused [[maybe_unused]] 201603L (C++17)
no_unique_address [[no_unique_address]] 201803L (C++20)
nodiscard [[nodiscard]] 201603L (C++17)
201907L (C++20)
noreturn [[noreturn]] 200809L (C++11)
unlikely [[unlikely]] 201803L (C++20)

[edit] Language features

The following macros are predefined in every translation unit. Each macro expands to an integer literal corresponding to the year and month when the corresponding feature has been included in the working draft.

When a feature changes significantly, the macro will be updated accordingly.

Macro name Feature Value Std
__cpp_aggregate_bases Aggregate classes with base classes 201603L (C++17)
__cpp_aggregate_nsdmi Aggregate classes with default member initializers 201304L (C++14)
__cpp_aggregate_paren_init Aggregate initialization in the form of direct initialization 201902L (C++20)
__cpp_alias_templates Alias templates 200704L (C++11)
__cpp_aligned_new Dynamic memory allocation for over-aligned data 201606L (C++17)
__cpp_attributes Attributes 200809L (C++11)
__cpp_binary_literals Binary literals 201304L (C++14)
__cpp_capture_star_this Lambda capture of *this by value as [=,*this] 201603L (C++17)
__cpp_char8_t char8_t 201811L (C++20)
__cpp_concepts Concepts 201907L (C++20)
__cpp_conditional_explicit explicit(bool) 201806L (C++20)
__cpp_consteval Immediate functions 201811L (C++20)
__cpp_constexpr constexpr 200704L (C++11)
Relaxed constexpr, non-const constexpr methods 201304L (C++14)
Constexpr lambda 201603L (C++17)
Trivial default initialization and asm-declaration in constexpr functions 201907L (C++20)
__cpp_constexpr_dynamic_alloc Operations for dynamic storage duration in constexpr functions 201907L (C++20)
__cpp_constexpr_in_decltype Less eager instantiation of constexpr functions 201711L (C++20)
__cpp_constinit constinit 201907L (C++20)
__cpp_decltype decltype 200707L (C++11)
__cpp_decltype_auto Return type deduction for normal functions 201304L (C++14)
__cpp_deduction_guides Template argument deduction for class templates 201703L (C++17)
CTAD for aggregates and aliases 201907L (C++20)
__cpp_delegating_constructors Delegating constructors 200604L (C++11)
__cpp_designated_initializers Designated initializer 201707L (C++20)
__cpp_enumerator_attributes Attributes for enumerators 201411L (C++17)
__cpp_fold_expressions Fold expressions 201603L (C++17)
__cpp_generic_lambdas Generic lambda expressions 201304L (C++14)
Familiar template syntax for generic lambdas 201707L (C++20)
__cpp_guaranteed_copy_elision Guaranteed copy elision through simplified value categories 201606L (C++17)
__cpp_hex_float Hexadecimal floating literals 201603L (C++17)
__cpp_if_constexpr constexpr if 201606L (C++17)
__cpp_impl_coroutine Coroutines (compiler support) 201902L (C++20)
__cpp_impl_destroying_delete Destroying operator delete (compiler support) 201806L (C++20)
__cpp_impl_three_way_comparison Three-way comparison (compiler support) 201907L (C++20)
__cpp_inheriting_constructors Inheriting constructors 200802L (C++11)
Rewording inheriting constructors 201511L (C++17)
__cpp_init_captures Lambda init-capture 201304L (C++14)
Allow pack expansion in lambda init-capture 201803L (C++20)
__cpp_initializer_lists List-initialization and std::initializer_list 200806L (C++11)
__cpp_inline_variables Inline variables 201606L (C++17)
__cpp_lambdas Lambda expressions 200907L (C++11)
__cpp_modules Modules 201907L (C++20)
__cpp_namespace_attributes Attributes for namespaces 201411L (C++17)
__cpp_noexcept_function_type Make exception specifications be part of the type system 201510L (C++17)
__cpp_nontype_template_args Allow constant evaluation for all non-type template arguments 201411L (C++17)
Class types and floating-point types in non-type template parameters 201911L (C++20)
__cpp_nontype_template_parameter_auto Declaring non-type template parameters with auto 201606L (C++17)
__cpp_nsdmi Non-static data member initializers 200809L (C++11)
__cpp_range_based_for Range-based for loop 200907L (C++11)
Range-based for loop with different begin/end types 201603L (C++17)
__cpp_raw_strings Raw string literals 200710L (C++11)
__cpp_ref_qualifiers ref-qualifiers 200710L (C++11)
__cpp_return_type_deduction Return type deduction for normal functions 201304L (C++14)
__cpp_rvalue_references Rvalue reference 200610L (C++11)
__cpp_sized_deallocation Sized deallocation 201309L (C++14)
__cpp_static_assert static_assert 200410L (C++11)
Single-argument static_assert 201411L (C++17)
__cpp_structured_bindings Structured bindings 201606L (C++17)
__cpp_template_template_args Matching of template template-arguments 201611L (C++17)
__cpp_threadsafe_static_init Dynamic initialization and destruction with concurrency 200806L (C++11)
__cpp_unicode_characters New character types (char16_t and char32_t) 200704L (C++11)
__cpp_unicode_literals Unicode string literals 200710L (C++11)
__cpp_user_defined_literals User-defined literals 200809L (C++11)
__cpp_using_enum Using enum 201907L (C++20)
__cpp_variable_templates Variable templates 201304L (C++14)
__cpp_variadic_templates Variadic templates 200704L (C++11)
__cpp_variadic_using Pack expansions in using-declarations 201611L (C++17)

[edit] Library features

The following macros are defined if the header <version> or any of the corresponding headers in the table below is included. Each macro expands to an integer literal corresponding to the year and month when the corresponding feature has been included in the working draft.

When a feature changes significantly, the macro will be updated accordingly.

Macro name Feature Value Header Std
__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 for std::reverse_iterator, std::move_iterator, std::array and range access 201603L <iterator> <array> (C++17)
ConstexprIterator; constexpr comparison for std::array; misc constexpr bits (std::array::fill et al.) 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 Floating point atomic 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 atomic lockfree integral types (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 Fixing atomic initialization (value-initialize std::atomic by default) 201911L <atomic> <memory> (C++20)
__cpp_lib_atomic_wait Efficient std::atomic waiting 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 Bit operations 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 Searchers 201603L <functional> (C++17)
__cpp_lib_byte std::byte 201603L <cstddef> (C++17)
__cpp_lib_char8_t Library support for char8_t 201907L <atomic> <filesystem> <istream> <limits> <locale> <ostream> <string> <string_view> (C++20)
__cpp_lib_chrono Rounding functions for std::chrono::duration and std::chrono::time_point 201510L <chrono> (C++17)
Constexpr for all the member functions of std::chrono::duration and std::chrono::time_point 201611L <chrono> (C++17)
Calendars and Time Zones 201907L <chrono> (C++20)
__cpp_lib_chrono_udls User-defined literals for time types 201304L <chrono> (C++14)
__cpp_lib_clamp std::clamp 201603L <algorithm> (C++17)
__cpp_lib_complex_udls User-defined Literals for std::complex 201309L <complex> (C++14)
__cpp_lib_concepts Standard library concepts 202002L <concepts> (C++20)
__cpp_lib_constexpr_algorithms Constexpr for algorithms 201806L <algorithm> (C++20)
__cpp_lib_constexpr_complex Constexpr for std::complex 201711L <complex> (C++20)
__cpp_lib_constexpr_dynamic_alloc Constexpr for std::allocator and related utilities 201907L <memory> (C++20)
__cpp_lib_constexpr_functional Misc constexpr bits (std::default_searcher); constexpr INVOKE 201907L <functional> (C++20)
__cpp_lib_constexpr_iterator Misc constexpr bits (std::insert_iterator et al.) 201811L <iterator> (C++20)
__cpp_lib_constexpr_memory Constexpr in std::pointer_traits 201811L <memory> (C++20)
__cpp_lib_constexpr_numeric Constexpr for <numeric> algorithms 201911L <numeric> (C++20)
__cpp_lib_constexpr_string Constexpr for std::string 201907L <string> (C++20)
__cpp_lib_constexpr_string_view Misc constexpr bits (std::string_view::copy) 201811L <string_view> (C++20)
__cpp_lib_constexpr_tuple Misc constexpr bits (std::tuple::operator= et al.) 201811L <tuple> (C++20)
__cpp_lib_constexpr_utility Misc constexpr bits (std::pair::operator= et al.) 201811L <utility> (C++20)
__cpp_lib_constexpr_vector Constexpr for std::vector 201907L <vector> (C++20)
__cpp_lib_coroutine Coroutines (library support) 201902L <coroutine> (C++20)
__cpp_lib_destroying_delete Destroying operator delete (library support) 201806L <new> (C++20)
__cpp_lib_enable_shared_from_this More precise specification of std::enable_shared_from_this 201603L <memory> (C++17)
__cpp_lib_endian std::endian 201907L <bit> (C++20)
__cpp_lib_erase_if Uniform container erasure 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 Execution policies 201603L <execution> (C++17)
std::execution::unsequenced_policy 201902L <execution> (C++20)
__cpp_lib_filesystem Filesystem library 201703L <filesystem> (C++17)
__cpp_lib_format Text formatting 201907L <format> (C++20)
__cpp_lib_gcd_lcm std::gcd, std::lcm 201606L <numeric> (C++17)
__cpp_lib_generic_associative_lookup Heterogeneous comparison lookup in associative containers 201304L <map> <set> (C++14)
__cpp_lib_generic_unordered_lookup Heterogeneous comparison lookup in unordered associative containers 201811L <unordered_map> <unordered_set> (C++20)
__cpp_lib_hardware_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-argument overload of std::hypot 201603L <cmath> (C++17)
__cpp_lib_incomplete_container_elements Minimal incomplete type support for standard containers 201505L <forward_list> <list> <vector> (C++17)
__cpp_lib_int_pow2 Integral power-of-2 operations (std::has_single_bit, std::bit_ceil, std::bit_floor, std::bit_length) 202002L <bit> (C++20)
__cpp_lib_integer_comparison_functions Integer comparison functions 202002L <utility> (C++20)
__cpp_lib_integer_sequence Compile-time integer sequences 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_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 Pointer-interconvertibility traits 201907L <type_traits> (C++20)
__cpp_lib_is_swappable [nothrow-]swappable traits 201603L <type_traits> (C++17)
__cpp_lib_jthread Stop token and joining thread 201911L <stop_token> <thread> (C++20)
__cpp_lib_latch std::latch 201907L <latch> (C++20)
__cpp_lib_launder Core Issue 1776: Replacement of class objects containing reference members (std::launder) 201606L <new> (C++17)
__cpp_lib_list_remove_return_type Change the return type of the remove(), remove_if() and unique() members of std::forward_list and std::list 201806L <forward_list> <list> (C++20)
__cpp_lib_logical_traits Logical operator type 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 Mathematical constants 201907L <numbers> (C++20)
__cpp_lib_math_special_functions Mathematical special functions for C++17 201603L <cmath> (C++17)
__cpp_lib_memory_resource std::pmr::memory_resource 201603L <memory_resource> (C++17)
__cpp_lib_node_extract Splicing maps and sets (std::map::extract, std::map::merge, std::map::insert(node_type), etc) 201606L <map> <set> <unordered_map> <unordered_set> (C++17)
__cpp_lib_nonmember_container_access std::size(), std::data() and 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 Parallel algorithms 201603L <algorithm> <numeric> (C++17)
__cpp_lib_polymorphic_allocator std::polymorphic_allocator<> as a vocabulary type 201902L <memory> (C++20)
__cpp_lib_quoted_string_io std::quoted 201304L <iomanip> (C++14)
__cpp_lib_ranges Ranges library and constrained algorithms 201911L <algorithm> <functional> <iterator> <memory> <ranges> (C++20)
__cpp_lib_raw_memory_algorithms Extending memory management tools 201606L <memory> (C++17)
__cpp_lib_remove_cvref std::remove_cvref 201711L <type_traits> (C++20)
__cpp_lib_result_of_sfinae std::result_of and SFINAE 201210L <type_traits> <functional> (C++14)
__cpp_lib_robust_nonmodifying_seq_ops Making non-modifying sequence operations more robust (two-range overloads for std::mismatch, std::equal and 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 (untimed) 201505L <shared_mutex> (C++17)
__cpp_lib_shared_ptr_arrays std::shared_ptr<T[]> 201611L <memory> (C++17)
Array support of 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 and std::shift_right 201806L <algorithm> (C++20)
__cpp_lib_smart_ptr_for_overwrite Smart pointer creation with default initialization (std::allocate_shared_for_overwrite, std::make_shared_for_overwrite, std::make_unique_for_overwrite) 202002L <memory> (C++20)
__cpp_lib_source_location Source-code information capture (std::source_location) 201907L <source_location> (C++20)
__cpp_lib_span std::span 202002L <span> (C++20)
__cpp_lib_ssize std::ssize and unsigned std::span::size 201902L <iterator> (C++20)
__cpp_lib_starts_ends_with String prefix and suffix checking (starts_with() and ends_with() for std::string and std::string_view) 201711L <string> <string_view> (C++20)
__cpp_lib_string_udls User-defined literals for string types 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 Synchronized buffered ostream (std::syncbuf, std::osyncstream) and manipulators 201803L <syncstream> (C++20)
__cpp_lib_three_way_comparison Three-way comparison (library support); adding three-way comparison to the library 201907L <compare> (C++20)
__cpp_lib_to_address Utility to convert a pointer to a raw pointer (std::to_address) 201711L <memory> (C++20)
__cpp_lib_to_array std::to_array 201907L <array> (C++20)
__cpp_lib_to_chars Elementary string conversions (std::to_chars, std::from_chars) 201611L <charconv> (C++17)
__cpp_lib_transformation_trait_aliases Alias templates for TransformationTraits 201304L <type_traits> (C++14)
__cpp_lib_transparent_operators Transparent operator functors (std::less<> et al) 201210L <functional> (C++14)
Transparent 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 Addressing 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 Type traits 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 and std::unwrap_reference 201811L <functional> (C++20)
__cpp_lib_variant std::variant: a type-safe union for C++17 201606L <variant> (C++17)
__cpp_lib_void_t std::void_t 201411L <type_traits> (C++17)

[edit] Example

#ifdef __has_include                           // Check if __has_include is present
#  if __has_include(<optional>)                // Check for a standard library
#    include <optional>
#  elif __has_include(<experimental/optional>) // Check for an experimental version
#    include <experimental/optional>
#  elif __has_include(<boost/optional.hpp>)    // Try with an external library
#    include <boost/optional.hpp>
#  else                                        // Not found at all
#     error "Missing <optional>"
#  endif
#endif
 
#ifdef __has_cpp_attribute                      // Check if __has_cpp_attribute is present
#  if __has_cpp_attribute(deprecated)           // Check for an attribute
#    define DEPRECATED(msg) [[deprecated(msg)]]
#  endif
#endif
#ifndef DEPRECATED
#    define DEPRECATED(msg)
#endif
 
DEPRECATED("foo() has been deprecated") void foo();
 
#if __cpp_constexpr >= 201304                   // Check for a specific version of a feature
#  define CONSTEXPR constexpr
#else
#  define CONSTEXPR inline
#endif
 
CONSTEXPR int bar(unsigned i)
{
#if __cpp_binary_literals                    // Check for the presence of a feature
    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()
{
}


[edit] Example

Following program dumps C++ compiler features and attributes.

#if __cplusplus < 201100
#  error "C++11 or better is required"
#endif
 
#include <algorithm>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <string>
 
#ifdef __has_include
# if __has_include(<version>)
#   include <version>
# endif
#endif
 
#define COMPILER_FEATURE_VALUE(value) #value
#define COMPILER_FEATURE_ENTRY(name) { #name, COMPILER_FEATURE_VALUE(name) },
 
#ifdef __has_cpp_attribute
# define COMPILER_ATTRIBUTE_VALUE_AS_STRING(s) #s
# define COMPILER_ATTRIBUTE_AS_NUMBER(x) COMPILER_ATTRIBUTE_VALUE_AS_STRING(x)
# define COMPILER_ATTRIBUTE_ENTRY(attr) \
  { #attr, COMPILER_ATTRIBUTE_AS_NUMBER(__has_cpp_attribute(attr)) },
#else
# define COMPILER_ATTRIBUTE_ENTRY(attr) { #attr, "_" },
#endif
 
// Change these options to print out only necessary info.
static struct PrintOptions {
    constexpr static bool titles               = 1;
    constexpr static bool attributes           = 1;
    constexpr static bool general_features     = 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 sorted_by_value      = 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                = 0;
}   print;
 
struct CompilerFeature {
    CompilerFeature(const char* name = nullptr, const char* value = nullptr)
        : name(name), value(value) {}
    const char* name; const char* value;
};
 
static CompilerFeature cxx[] = {
COMPILER_FEATURE_ENTRY(__cplusplus)
COMPILER_FEATURE_ENTRY(__cpp_exceptions)
COMPILER_FEATURE_ENTRY(__cpp_rtti)
#if 0
COMPILER_FEATURE_ENTRY(__GNUC__)
COMPILER_FEATURE_ENTRY(__GNUC_MINOR__)
COMPILER_FEATURE_ENTRY(__GNUC_PATCHLEVEL__)
COMPILER_FEATURE_ENTRY(__GNUG__)
COMPILER_FEATURE_ENTRY(__clang__)
COMPILER_FEATURE_ENTRY(__clang_major__)
COMPILER_FEATURE_ENTRY(__clang_minor__)
COMPILER_FEATURE_ENTRY(__clang_patchlevel__)
#endif
};
static CompilerFeature cxx11[] = {
COMPILER_FEATURE_ENTRY(__cpp_alias_templates)
COMPILER_FEATURE_ENTRY(__cpp_attributes)
COMPILER_FEATURE_ENTRY(__cpp_constexpr)
COMPILER_FEATURE_ENTRY(__cpp_decltype)
COMPILER_FEATURE_ENTRY(__cpp_delegating_constructors)
COMPILER_FEATURE_ENTRY(__cpp_inheriting_constructors)
COMPILER_FEATURE_ENTRY(__cpp_initializer_lists)
COMPILER_FEATURE_ENTRY(__cpp_lambdas)
COMPILER_FEATURE_ENTRY(__cpp_nsdmi)
COMPILER_FEATURE_ENTRY(__cpp_range_based_for)
COMPILER_FEATURE_ENTRY(__cpp_raw_strings)
COMPILER_FEATURE_ENTRY(__cpp_ref_qualifiers)
COMPILER_FEATURE_ENTRY(__cpp_rvalue_references)
COMPILER_FEATURE_ENTRY(__cpp_static_assert)
COMPILER_FEATURE_ENTRY(__cpp_threadsafe_static_init)
COMPILER_FEATURE_ENTRY(__cpp_unicode_characters)
COMPILER_FEATURE_ENTRY(__cpp_unicode_literals)
COMPILER_FEATURE_ENTRY(__cpp_user_defined_literals)
COMPILER_FEATURE_ENTRY(__cpp_variadic_templates)
};
static CompilerFeature cxx14[] = {
COMPILER_FEATURE_ENTRY(__cpp_aggregate_nsdmi)
COMPILER_FEATURE_ENTRY(__cpp_binary_literals)
COMPILER_FEATURE_ENTRY(__cpp_constexpr)
COMPILER_FEATURE_ENTRY(__cpp_decltype_auto)
COMPILER_FEATURE_ENTRY(__cpp_generic_lambdas)
COMPILER_FEATURE_ENTRY(__cpp_init_captures)
COMPILER_FEATURE_ENTRY(__cpp_return_type_deduction)
COMPILER_FEATURE_ENTRY(__cpp_sized_deallocation)
COMPILER_FEATURE_ENTRY(__cpp_variable_templates)
};
static CompilerFeature cxx14lib[] = {
COMPILER_FEATURE_ENTRY(__cpp_lib_chrono_udls)
COMPILER_FEATURE_ENTRY(__cpp_lib_complex_udls)
COMPILER_FEATURE_ENTRY(__cpp_lib_exchange_function)
COMPILER_FEATURE_ENTRY(__cpp_lib_generic_associative_lookup)
COMPILER_FEATURE_ENTRY(__cpp_lib_integer_sequence)
COMPILER_FEATURE_ENTRY(__cpp_lib_integral_constant_callable)
COMPILER_FEATURE_ENTRY(__cpp_lib_is_final)
COMPILER_FEATURE_ENTRY(__cpp_lib_is_null_pointer)
COMPILER_FEATURE_ENTRY(__cpp_lib_make_reverse_iterator)
COMPILER_FEATURE_ENTRY(__cpp_lib_make_unique)
COMPILER_FEATURE_ENTRY(__cpp_lib_null_iterators)
COMPILER_FEATURE_ENTRY(__cpp_lib_quoted_string_io)
COMPILER_FEATURE_ENTRY(__cpp_lib_result_of_sfinae)
COMPILER_FEATURE_ENTRY(__cpp_lib_robust_nonmodifying_seq_ops)
COMPILER_FEATURE_ENTRY(__cpp_lib_shared_timed_mutex)
COMPILER_FEATURE_ENTRY(__cpp_lib_string_udls)
COMPILER_FEATURE_ENTRY(__cpp_lib_transformation_trait_aliases)
COMPILER_FEATURE_ENTRY(__cpp_lib_transparent_operators)
COMPILER_FEATURE_ENTRY(__cpp_lib_tuple_element_t)
COMPILER_FEATURE_ENTRY(__cpp_lib_tuples_by_type)
};
 
static CompilerFeature cxx17[] = {
COMPILER_FEATURE_ENTRY(__cpp_aggregate_bases)
COMPILER_FEATURE_ENTRY(__cpp_aligned_new)
COMPILER_FEATURE_ENTRY(__cpp_capture_star_this)
COMPILER_FEATURE_ENTRY(__cpp_constexpr)
COMPILER_FEATURE_ENTRY(__cpp_deduction_guides)
COMPILER_FEATURE_ENTRY(__cpp_enumerator_attributes)
COMPILER_FEATURE_ENTRY(__cpp_fold_expressions)
COMPILER_FEATURE_ENTRY(__cpp_guaranteed_copy_elision)
COMPILER_FEATURE_ENTRY(__cpp_hex_float)
COMPILER_FEATURE_ENTRY(__cpp_if_constexpr)
COMPILER_FEATURE_ENTRY(__cpp_inheriting_constructors)
COMPILER_FEATURE_ENTRY(__cpp_inline_variables)
COMPILER_FEATURE_ENTRY(__cpp_namespace_attributes)
COMPILER_FEATURE_ENTRY(__cpp_noexcept_function_type)
COMPILER_FEATURE_ENTRY(__cpp_nontype_template_args)
COMPILER_FEATURE_ENTRY(__cpp_nontype_template_parameter_auto)
COMPILER_FEATURE_ENTRY(__cpp_range_based_for)
COMPILER_FEATURE_ENTRY(__cpp_static_assert)
COMPILER_FEATURE_ENTRY(__cpp_structured_bindings)
COMPILER_FEATURE_ENTRY(__cpp_template_template_args)
COMPILER_FEATURE_ENTRY(__cpp_variadic_using)
};
static CompilerFeature cxx17lib[] = {
COMPILER_FEATURE_ENTRY(__cpp_lib_addressof_constexpr)
COMPILER_FEATURE_ENTRY(__cpp_lib_allocator_traits_is_always_equal)
COMPILER_FEATURE_ENTRY(__cpp_lib_any)
COMPILER_FEATURE_ENTRY(__cpp_lib_apply)
COMPILER_FEATURE_ENTRY(__cpp_lib_array_constexpr)
COMPILER_FEATURE_ENTRY(__cpp_lib_as_const)
COMPILER_FEATURE_ENTRY(__cpp_lib_atomic_is_always_lock_free)
COMPILER_FEATURE_ENTRY(__cpp_lib_bool_constant)
COMPILER_FEATURE_ENTRY(__cpp_lib_boyer_moore_searcher)
COMPILER_FEATURE_ENTRY(__cpp_lib_byte)
COMPILER_FEATURE_ENTRY(__cpp_lib_chrono)
COMPILER_FEATURE_ENTRY(__cpp_lib_clamp)
COMPILER_FEATURE_ENTRY(__cpp_lib_enable_shared_from_this)
COMPILER_FEATURE_ENTRY(__cpp_lib_execution)
COMPILER_FEATURE_ENTRY(__cpp_lib_filesystem)
COMPILER_FEATURE_ENTRY(__cpp_lib_gcd_lcm)
COMPILER_FEATURE_ENTRY(__cpp_lib_hardware_interference_size)
COMPILER_FEATURE_ENTRY(__cpp_lib_has_unique_object_representations)
COMPILER_FEATURE_ENTRY(__cpp_lib_hypot)
COMPILER_FEATURE_ENTRY(__cpp_lib_incomplete_container_elements)
COMPILER_FEATURE_ENTRY(__cpp_lib_invoke)
COMPILER_FEATURE_ENTRY(__cpp_lib_is_aggregate)
COMPILER_FEATURE_ENTRY(__cpp_lib_is_invocable)
COMPILER_FEATURE_ENTRY(__cpp_lib_is_swappable)
COMPILER_FEATURE_ENTRY(__cpp_lib_launder)
COMPILER_FEATURE_ENTRY(__cpp_lib_logical_traits)
COMPILER_FEATURE_ENTRY(__cpp_lib_make_from_tuple)
COMPILER_FEATURE_ENTRY(__cpp_lib_map_try_emplace)
COMPILER_FEATURE_ENTRY(__cpp_lib_math_special_functions)
COMPILER_FEATURE_ENTRY(__cpp_lib_memory_resource)
COMPILER_FEATURE_ENTRY(__cpp_lib_node_extract)
COMPILER_FEATURE_ENTRY(__cpp_lib_nonmember_container_access)
COMPILER_FEATURE_ENTRY(__cpp_lib_not_fn)
COMPILER_FEATURE_ENTRY(__cpp_lib_optional)
COMPILER_FEATURE_ENTRY(__cpp_lib_parallel_algorithm)
COMPILER_FEATURE_ENTRY(__cpp_lib_raw_memory_algorithms)
COMPILER_FEATURE_ENTRY(__cpp_lib_sample)
COMPILER_FEATURE_ENTRY(__cpp_lib_scoped_lock)
COMPILER_FEATURE_ENTRY(__cpp_lib_shared_mutex)
COMPILER_FEATURE_ENTRY(__cpp_lib_shared_ptr_arrays)
COMPILER_FEATURE_ENTRY(__cpp_lib_shared_ptr_weak_type)
COMPILER_FEATURE_ENTRY(__cpp_lib_string_view)
COMPILER_FEATURE_ENTRY(__cpp_lib_to_chars)
COMPILER_FEATURE_ENTRY(__cpp_lib_transparent_operators)
COMPILER_FEATURE_ENTRY(__cpp_lib_type_trait_variable_templates)
COMPILER_FEATURE_ENTRY(__cpp_lib_uncaught_exceptions)
COMPILER_FEATURE_ENTRY(__cpp_lib_unordered_map_try_emplace)
COMPILER_FEATURE_ENTRY(__cpp_lib_variant)
COMPILER_FEATURE_ENTRY(__cpp_lib_void_t)
};
 
static CompilerFeature cxx20[] = {
COMPILER_FEATURE_ENTRY(__cpp_aggregate_paren_init)
COMPILER_FEATURE_ENTRY(__cpp_char8_t)
COMPILER_FEATURE_ENTRY(__cpp_concepts)
COMPILER_FEATURE_ENTRY(__cpp_conditional_explicit)
COMPILER_FEATURE_ENTRY(__cpp_consteval)
COMPILER_FEATURE_ENTRY(__cpp_constexpr)
COMPILER_FEATURE_ENTRY(__cpp_constexpr_dynamic_alloc)
COMPILER_FEATURE_ENTRY(__cpp_constexpr_in_decltype)
COMPILER_FEATURE_ENTRY(__cpp_constinit)
COMPILER_FEATURE_ENTRY(__cpp_deduction_guides)
COMPILER_FEATURE_ENTRY(__cpp_designated_initializers)
COMPILER_FEATURE_ENTRY(__cpp_generic_lambdas)
COMPILER_FEATURE_ENTRY(__cpp_impl_coroutine)
COMPILER_FEATURE_ENTRY(__cpp_impl_destroying_delete)
COMPILER_FEATURE_ENTRY(__cpp_impl_three_way_comparison)
COMPILER_FEATURE_ENTRY(__cpp_init_captures)
COMPILER_FEATURE_ENTRY(__cpp_modules)
COMPILER_FEATURE_ENTRY(__cpp_nontype_template_args)
COMPILER_FEATURE_ENTRY(__cpp_using_enum)
};
static CompilerFeature cxx20lib[] = {
COMPILER_FEATURE_ENTRY(__cpp_lib_array_constexpr)
COMPILER_FEATURE_ENTRY(__cpp_lib_assume_aligned)
COMPILER_FEATURE_ENTRY(__cpp_lib_atomic_flag_test)
COMPILER_FEATURE_ENTRY(__cpp_lib_atomic_float)
COMPILER_FEATURE_ENTRY(__cpp_lib_atomic_lock_free_type_aliases)
COMPILER_FEATURE_ENTRY(__cpp_lib_atomic_ref)
COMPILER_FEATURE_ENTRY(__cpp_lib_atomic_shared_ptr)
COMPILER_FEATURE_ENTRY(__cpp_lib_atomic_value_initialization)
COMPILER_FEATURE_ENTRY(__cpp_lib_atomic_wait)
COMPILER_FEATURE_ENTRY(__cpp_lib_barrier)
COMPILER_FEATURE_ENTRY(__cpp_lib_bind_front)
COMPILER_FEATURE_ENTRY(__cpp_lib_bit_cast)
COMPILER_FEATURE_ENTRY(__cpp_lib_bitops)
COMPILER_FEATURE_ENTRY(__cpp_lib_bounded_array_traits)
COMPILER_FEATURE_ENTRY(__cpp_lib_char8_t)
COMPILER_FEATURE_ENTRY(__cpp_lib_chrono)
COMPILER_FEATURE_ENTRY(__cpp_lib_concepts)
COMPILER_FEATURE_ENTRY(__cpp_lib_constexpr_algorithms)
COMPILER_FEATURE_ENTRY(__cpp_lib_constexpr_complex)
COMPILER_FEATURE_ENTRY(__cpp_lib_constexpr_dynamic_alloc)
COMPILER_FEATURE_ENTRY(__cpp_lib_constexpr_functional)
COMPILER_FEATURE_ENTRY(__cpp_lib_constexpr_iterator)
COMPILER_FEATURE_ENTRY(__cpp_lib_constexpr_memory)
COMPILER_FEATURE_ENTRY(__cpp_lib_constexpr_numeric)
COMPILER_FEATURE_ENTRY(__cpp_lib_constexpr_string)
COMPILER_FEATURE_ENTRY(__cpp_lib_constexpr_string_view)
COMPILER_FEATURE_ENTRY(__cpp_lib_constexpr_tuple)
COMPILER_FEATURE_ENTRY(__cpp_lib_constexpr_utility)
COMPILER_FEATURE_ENTRY(__cpp_lib_constexpr_vector)
COMPILER_FEATURE_ENTRY(__cpp_lib_coroutine)
COMPILER_FEATURE_ENTRY(__cpp_lib_destroying_delete)
COMPILER_FEATURE_ENTRY(__cpp_lib_endian)
COMPILER_FEATURE_ENTRY(__cpp_lib_erase_if)
COMPILER_FEATURE_ENTRY(__cpp_lib_execution)
COMPILER_FEATURE_ENTRY(__cpp_lib_format)
COMPILER_FEATURE_ENTRY(__cpp_lib_generic_unordered_lookup)
COMPILER_FEATURE_ENTRY(__cpp_lib_int_pow2)
COMPILER_FEATURE_ENTRY(__cpp_lib_integer_comparison_functions)
COMPILER_FEATURE_ENTRY(__cpp_lib_interpolate)
COMPILER_FEATURE_ENTRY(__cpp_lib_is_constant_evaluated)
COMPILER_FEATURE_ENTRY(__cpp_lib_is_layout_compatible)
COMPILER_FEATURE_ENTRY(__cpp_lib_is_nothrow_convertible)
COMPILER_FEATURE_ENTRY(__cpp_lib_is_pointer_interconvertible)
COMPILER_FEATURE_ENTRY(__cpp_lib_jthread)
COMPILER_FEATURE_ENTRY(__cpp_lib_latch)
COMPILER_FEATURE_ENTRY(__cpp_lib_list_remove_return_type)
COMPILER_FEATURE_ENTRY(__cpp_lib_math_constants)
COMPILER_FEATURE_ENTRY(__cpp_lib_polymorphic_allocator)
COMPILER_FEATURE_ENTRY(__cpp_lib_ranges)
COMPILER_FEATURE_ENTRY(__cpp_lib_remove_cvref)
COMPILER_FEATURE_ENTRY(__cpp_lib_semaphore)
COMPILER_FEATURE_ENTRY(__cpp_lib_shared_ptr_arrays)
COMPILER_FEATURE_ENTRY(__cpp_lib_shift)
COMPILER_FEATURE_ENTRY(__cpp_lib_smart_ptr_for_overwrite)
COMPILER_FEATURE_ENTRY(__cpp_lib_source_location)
COMPILER_FEATURE_ENTRY(__cpp_lib_span)
COMPILER_FEATURE_ENTRY(__cpp_lib_ssize)
COMPILER_FEATURE_ENTRY(__cpp_lib_starts_ends_with)
COMPILER_FEATURE_ENTRY(__cpp_lib_string_view)
COMPILER_FEATURE_ENTRY(__cpp_lib_syncbuf)
COMPILER_FEATURE_ENTRY(__cpp_lib_three_way_comparison)
COMPILER_FEATURE_ENTRY(__cpp_lib_to_address)
COMPILER_FEATURE_ENTRY(__cpp_lib_to_array)
COMPILER_FEATURE_ENTRY(__cpp_lib_type_identity)
COMPILER_FEATURE_ENTRY(__cpp_lib_unwrap_ref)
};
 
static CompilerFeature cxx23[] = {
COMPILER_FEATURE_ENTRY(__cpp_cxx23_stub) //< Populate eventually
};
static CompilerFeature cxx23lib[] = {
COMPILER_FEATURE_ENTRY(__cpp_lib_cxx23_stub) //< Populate eventually
};
 
static CompilerFeature attributes[] = {
COMPILER_ATTRIBUTE_ENTRY(carries_dependency)
COMPILER_ATTRIBUTE_ENTRY(deprecated)
COMPILER_ATTRIBUTE_ENTRY(fallthrough)
COMPILER_ATTRIBUTE_ENTRY(likely)
COMPILER_ATTRIBUTE_ENTRY(maybe_unused)
COMPILER_ATTRIBUTE_ENTRY(nodiscard)
COMPILER_ATTRIBUTE_ENTRY(noreturn)
COMPILER_ATTRIBUTE_ENTRY(no_unique_address)
COMPILER_ATTRIBUTE_ENTRY(unlikely)
};
 
constexpr bool is_feature_supported(const CompilerFeature& x) {
    return x.value[0] != '_' && x.value[0] != '0' ;
}
 
inline void print_compiler_feature(const CompilerFeature& x) {
    constexpr static int max_name_length = 44; //< Update if necessary
    std::string value{ is_feature_supported(x) ? x.value : "------" };
    if (value.back() == 'L') value.pop_back(); //~ 201603L -> 201603
    // value.insert(4, 1, '-'); //~ 201603 -> 2016-03
    if ( (print.supported_features && is_feature_supported(x))
        || (print.unsupported_features && !is_feature_supported(x))) {
            std::cout << std::left << std::setw(max_name_length)
                      << x.name << " " << value << '\n';
    }
}
 
template<size_t N>
inline void show(char const* title, CompilerFeature (&features)[N]) {
    if (print.titles) {
        std::cout << '\n' << std::left << title << '\n';
    }
    if (print.sorted_by_value) {
        std::sort(std::begin(features), std::end(features),
            [](CompilerFeature const& lhs, CompilerFeature const& rhs) {
                return std::strcmp(lhs.value, rhs.value) < 0;
            });
    }
    for (const CompilerFeature& x : features) {
        print_compiler_feature(x);
    }
}
 
int main() {
    if (print.general_features) show("C++ GENERAL", cxx);
    if (print.cxx11 && print.core_features) show("C++11 CORE", cxx11);
    if (print.cxx14 && print.core_features) show("C++14 CORE", cxx14);
    if (print.cxx14 && print.lib_features ) show("C++14 LIB" , cxx14lib);
    if (print.cxx17 && print.core_features) show("C++17 CORE", cxx17);
    if (print.cxx17 && print.lib_features ) show("C++17 LIB" , cxx17lib);
    if (print.cxx20 && print.core_features) show("C++20 CORE", cxx20);
    if (print.cxx20 && print.lib_features ) show("C++20 LIB" , cxx20lib);
    if (print.cxx23 && print.core_features) show("C++23 CORE", cxx23);
    if (print.cxx23 && print.lib_features ) show("C++23 LIB" , cxx23lib);
    if (print.attributes) show("ATTRIBUTES", attributes);
}

Possible output:

C++ GENERAL
__cplusplus                                  202002
__cpp_exceptions                             199711
__cpp_rtti                                   199711
 
C++11 CORE
__cpp_alias_templates                        200704
__cpp_attributes                             200809
__cpp_constexpr                              201907
__cpp_decltype                               200707
__cpp_delegating_constructors                200604
__cpp_inheriting_constructors                201511
__cpp_initializer_lists                      200806
__cpp_lambdas                                200907
__cpp_nsdmi                                  200809
__cpp_range_based_for                        201603
__cpp_raw_strings                            200710
__cpp_ref_qualifiers                         200710
__cpp_rvalue_references                      200610
__cpp_static_assert                          201411
__cpp_threadsafe_static_init                 200806
__cpp_unicode_characters                     200704
__cpp_unicode_literals                       200710
__cpp_user_defined_literals                  200809
__cpp_variadic_templates                     200704
 
C++14 CORE
__cpp_aggregate_nsdmi                        201304
__cpp_binary_literals                        201304
__cpp_constexpr                              201907
__cpp_decltype_auto                          201304
__cpp_generic_lambdas                        201707
__cpp_init_captures                          201803
__cpp_return_type_deduction                  201304
__cpp_sized_deallocation                     ------
__cpp_variable_templates                     201304
 
... truncated ...

[edit] See Also