Feature testing (since C++20)
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.
Attributes
__has_cpp_attribute( attribute-token )
|
|||||||||
Checks for the support of an attribute named by attribute-token (after macro expansion).
For each standard attribute, it is implementation-defined whether __has_cpp_attribute expands to the value given in the table below (which is the year and month in which the attribute was added to the working draft) or 0. It will expand to given value in the table if and only if the standard attribute causes the implementation to behave as recommended (issuing diagnostic messages, affecting class layout, etc.).
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,
#elifdef,
#elifndef(since C++23) and defined but cannot be used anywhere else.
| attribute-token | Attribute | Value | Std | Paper(s) |
|---|---|---|---|---|
assume
|
[[assume]]
|
202207L
|
(C++23) | P1774R8 |
carries_dependency
|
[[carries_dependency]]
|
200809L
|
(C++11) (until C++26) |
N2556 N2643 P3475R2 |
deprecated
|
[[deprecated]]
|
201309L
|
(C++14) | N3760 |
fallthrough
|
[[fallthrough]]
|
201603L
|
(C++17) | P0188R1 |
indeterminate
|
[[indeterminate]]
|
202403L
|
(C++26) | P2795R5 |
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 |
[[nodiscard]] with reason
|
201907L
|
(C++20) | P1301R4 | |
noreturn
|
[[noreturn]]
|
200809L
|
(C++11) | N2761 |
unlikely
|
[[unlikely]]
|
201803L
|
(C++20) | P0479R5 |
| Total number of attributes: 11 | ||||
Language features
The following macros can be used to detect whether a language feature is implemented by the current implementation. They 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 | Paper(s) |
|---|---|---|---|---|
__cpp_aggregate_
|
Aggregate classes with base classes | 201603L
|
(C++17) | P0017R1 |
__cpp_aggregate_
|
Aggregate classes with default member initializers | 201304L
|
(C++14) | N3653 |
__cpp_aggregate_
|
Aggregate initialization in the form of direct initialization | 201902L
|
(C++20) | P0960R3 |
__cpp_alias_templates
|
Alias templates | 200704L
|
(C++11) | N2258 |
__cpp_aligned_new
|
Dynamic memory allocation for over-aligned data | 201606L
|
(C++17) | P0035R4 |
__cpp_attributes
|
Attributes | 200809L
|
(C++11) | N2761 |
__cpp_auto_cast
|
Casting an expression to a prvalue (auto(x))
|
202110L
|
(C++23) | P0849R8 |
__cpp_binary_literals
|
Binary literals | 201304L
|
(C++14) | N3472 |
__cpp_capture_star_
|
Lambda capture of *this by value as [=,*this]
|
201603L
|
(C++17) | P0018R3 |
__cpp_char8_t
|
char8_t | 201811L
|
(C++20) | P0482R6 |
char8_t compatibility and portability fix (allow initialization of (unsigned) char arrays from UTF-8 string literals)
|
202207L
|
(C++23) (DR20) |
P2513R4 | |
__cpp_concepts
|
Concepts | 201907L
|
(C++20) | P0734R0 P1084R2 P1452R2 |
| Conditional trivial special member functions | 202002L
|
P0848R3 P2493R0 | ||
__cpp_conditional_
|
Conditional explicit specifier
|
201806L
|
(C++20) | P0892R2 |
__cpp_consteval
|
Immediate functions | 201811L
|
(C++20) | P1073R3 |
| Making consteval propagate up | 202211L
|
(C++23) (DR20) |
P2564R3 | |
__cpp_constexpr
|
constexpr | 200704L
|
(C++11) | N2235 |
Relaxed constexpr, non-const constexpr methods
|
201304L
|
(C++14) | N3652 | |
| Constexpr lambda | 201603L
|
(C++17) | P0170R1 | |
Virtual function calls in constant expressions; try blocks in constexpr functions, dynamic_cast and polymorphic typeid in constant expressions; trivial default initialization and asm-declaration in constexpr functions
|
201907L
|
(C++20) | P1064R0 P1002R1 P1327R1 P1331R2 P1668R1 | |
| Changing the active member of a union in constant evaluation | 202002L
|
P1330R0 P2493R0 | ||
| Non-literal variables, labels, and goto statements in constexpr functions | 202110L
|
(C++23) | P2242R3 | |
| Relaxing some restrictions on constexpr functions and function templates | 202207L
|
P2448R2 | ||
| Permitting static constexpr variables in constexpr functions | 202211L
|
P2647R1 | ||
Constexpr cast from void*: towards constexpr type-erasure
|
202306L
|
(C++26) | P2738R1 | |
Constexpr placement new
|
202406L
|
P2747R2 | ||
__cpp_constexpr_
|
Operations for dynamic storage duration in constexpr functions | 201907L
|
(C++20) | P0784R7 |
__cpp_constexpr_
|
Constexpr exceptions | 202411L
|
(C++26) | P3068R6 |
__cpp_constexpr_
|
Generation of function and variable definitions when needed for constant evaluation | 201711L
|
(C++20) (DR11) |
P0859R0 |
__cpp_constinit
|
constinit | 201907L
|
(C++20) | P1143R2 |
__cpp_contracts
|
Contracts | 202502L
|
(C++26) | P2900R14 |
__cpp_decltype
|
decltype | 200707L
|
(C++11) | N2343 |
__cpp_decltype_auto
|
Return type deduction for normal functions | 201304L
|
(C++14) | N3638 |
__cpp_deduction_
|
Template argument deduction for class templates (CTAD) | 201703L
|
(C++17) | P0091R3 P0512R0 P0620R0 |
| CTAD for aggregates and aliases | 201907L
|
(C++20) | P1814R0 P1816R0 | |
__cpp_delegating_
|
Delegating constructors | 200604L
|
(C++11) | N1986 |
__cpp_deleted_function
|
Deleted function definitions with messages (= delete("should have a reason");)
|
202403L
|
(C++26) | P2573R2 |
__cpp_designated_
|
Designated initializers | 201707L
|
(C++20) | P0329R4 |
__cpp_enumerator_
|
Attributes for enumerators | 201411L
|
(C++17) | N4266 |
__cpp_explicit_this_
|
Explicit object parameter | 202110L
|
(C++23) | P0847R7 |
__cpp_fold_expressions
|
Fold expressions | 201603L
|
(C++17) | N4295 P0036R0 |
__cpp_generic_lambdas
|
Generic lambda expressions | 201304L
|
(C++14) | N3649 |
| Explicit template parameter list for generic lambdas | 201707L
|
(C++20) | P0428R2 | |
__cpp_guaranteed_
|
Guaranteed copy elision through simplified value categories | 201606L
|
(C++17) | P0135R1 |
__cpp_hex_float
|
Hexadecimal floating literals | 201603L
|
(C++17) | P0245R1 |
__cpp_if_consteval
|
if consteval
|
202106L
|
(C++23) | P1938R3 |
__cpp_if_constexpr
|
if constexpr
|
201606L
|
(C++17) | P0292R2 |
__cpp_impl_coroutine
|
Coroutines (compiler support) | 201902L
|
(C++20) | P0912R5 LWG3393 |
__cpp_impl_destroying_
|
Destroying operator delete (compiler support)
|
201806L
|
(C++20) | P0722R3 |
__cpp_impl_three_
|
Three-way comparison (compiler support) | 201907L
|
(C++20) | P0515R3 P0768R1 P1185R2 P1630R1 |
__cpp_implicit_move
|
Simpler implicit move | 202207L
|
(C++23) | P2266R3 |
__cpp_inheriting_
|
Inheriting constructors | 200802L
|
(C++11) | N2540 |
| New specification for inheriting constructors | 201511L
|
(C++17) (DR11) |
P0136R1 | |
__cpp_init_captures
|
Lambda init-capture | 201304L
|
(C++14) | N3648 |
| Allow pack expansion in lambda init-capture | 201803L
|
(C++20) | P0780R2 | |
__cpp_initializer_
|
List-initialization and std::initializer_list | 200806L
|
(C++11) | N2672 |
__cpp_inline_variables
|
Inline variables | 201606L
|
(C++17) | P0386R2 |
__cpp_lambdas
|
Lambda expressions | 200907L
|
(C++11) | N2927 |
__cpp_modules
|
Modules | 201907L
|
(C++20) | P1103R3 P1811R0 |
__cpp_multidimensional_
|
Multidimensional subscript operator | 202110L
|
(C++23) | P2128R6 |
| Static operator[] | 202211L
|
P2589R1 | ||
__cpp_named_character_
|
Named universal character escapes | 202207L
|
(C++23) | P2071R2 |
__cpp_namespace_
|
Attributes for namespaces | 201411L
|
(C++17) | N4266 |
__cpp_noexcept_function_
|
Make exception specifications be part of the type system | 201510L
|
(C++17) | P0012R1 |
__cpp_nontype_template_
|
Allow constant evaluation for all non-type template arguments | 201411L
|
(C++17) | N4268 |
| Class types and floating-point types in non-type template parameters | 201911L
|
(C++20) | P1907R1 | |
__cpp_nontype_template_
|
Declaring non-type template parameter with auto
|
201606L
|
(C++17) | P0127R2 |
__cpp_nsdmi
|
Non-static data member initializers | 200809L
|
(C++11) | N2756 |
__cpp_pack_indexing
|
Pack indexing | 202311L
|
(C++26) | P2662R3 |
__cpp_placeholder_
|
A nice placeholder with no name | 202306L
|
(C++26) | P2169R4 |
__cpp_pp_embed
|
#embed | 202502L
|
(C++26) | P1967R14 |
__cpp_range_based_
|
Range-based for loop
|
200907L
|
(C++11) | N2930 |
Range-based for loop with different begin/end types
|
201603L
|
(C++17) | P0184R0 | |
Lifetime extension in range-based for
|
202211L
|
(C++23) | P2644R1 P2718R0 CWG2659 | |
__cpp_raw_strings
|
Raw string literals | 200710L
|
(C++11) | N2442 |
__cpp_ref_qualifiers
|
ref-qualifiers | 200710L
|
(C++11) | N2439 |
__cpp_return_type_
|
Return type deduction for normal functions | 201304L
|
(C++14) | N3638 |
__cpp_rvalue_references
|
Rvalue reference | 200610L
|
(C++11) | N2118 |
__cpp_size_t_suffix
|
Literal suffixes for std::size_t and its signed version
|
202011L
|
(C++23) | P0330R8 |
__cpp_sized_deallocation
|
Sized deallocation | 201309L
|
(C++14) | N3778 |
__cpp_static_assert
|
static_assert | 200410L
|
(C++11) | N1720 |
Single-argument static_assert
|
201411L
|
(C++17) | N3928 | |
User-generated static_assert messages
|
202306L
|
(C++26) | P2741R3 | |
__cpp_static_call_
|
Static operator() | 202207L
|
(C++23) | P1169R4 |
__cpp_structured_
|
Structured bindings | 201606L
|
(C++17) | P0217R3 |
| Attributes for structured binding | 202403L
|
(C++26) | P0609R3 | |
| Structured bindings can introduce a pack | 202411L
|
P1061R10 | ||
__cpp_template_parameters
|
Concept and variable-template template-parameters | 202502L
|
(C++26) | P2841R7 |
__cpp_template_template_
|
Matching of template template arguments | 201611L
|
(C++17) | P0522R0 |
__cpp_threadsafe_
|
Dynamic initialization and destruction with concurrency | 200806L
|
(C++11) | N2660 |
__cpp_trivial_union
|
Trivial unions | 202502L
|
(C++26) | P3074R7 |
__cpp_unicode_characters
|
New character types (char16_t and char32_t)
|
200704L
|
(C++11) | N2249 |
__cpp_unicode_literals
|
Unicode string literals | 200710L
|
(C++11) | N2442 |
__cpp_user_defined_
|
User-defined literals | 200809L
|
(C++11) | N2765 |
__cpp_using_enum
|
using enum | 201907L
|
(C++20) | P1099R5 |
__cpp_variable_templates
|
Variable templates | 201304L
|
(C++14) | N3651 |
__cpp_variadic_friend
|
Variadic friend declarations | 202403L
|
(C++26) | P2893R3 |
__cpp_variadic_templates
|
Variadic templates | 200704L
|
(C++11) | N2242 |
__cpp_variadic_using
|
Pack expansions in using-declarations
|
201611L
|
(C++17) | P0195R2 |
| Total number of macros: 75 | ||||
Library features
The following macros can be used to detect whether a standard library feature is implemented by the current implementation. Unlike the language feature test macros, they are not predefined. Instead, they are provided by the header <version>.
For each library feature test macro, it is also provided by the headers that provide the relevant standard library components. See library feature test macros for a complete list of headers providing these macros.
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 | Paper(s) |
|---|---|---|---|---|
__cpp_lib_adaptor_
|
Iterator pair constructors for std::stack and std::queue | 202106L
|
(C++23) | P1425R4 |
__cpp_lib_addressof_
|
Constexpr std::addressof | 201603L
|
(C++17) | LWG2296 |
__cpp_lib_algorithm_
|
Enabling list-initialization for algorithms | 202403L
|
(C++26) | P2248R8 P3217R0 |
__cpp_lib_algorithm_
|
Ranges iterators as inputs to non-Ranges algorithms | 202207L
|
(C++23) | P2408R5 |
__cpp_lib_aligned_
|
std::aligned_accessor: an std::mdspan accessor expressing pointer over-alignment | 202411L
|
(C++26) | P2897R7 |
__cpp_lib_allocate_
|
Size-feedback in the allocator interface, e.g.: std::allocator::allocate_at_least, std::allocator_traits::allocate_at_least | 202302L
|
(C++23) | P0401R6 P2652R2 LWG3887 |
__cpp_lib_allocator_
|
std::allocator_traits::is_always_equal, noexcept cleanups
|
201411L
|
(C++17) | N4258 |
__cpp_lib_any
|
std::any | 201606L
|
(C++17) | P0220R1 P0032R3 |
__cpp_lib_apply
|
std::apply | 201603L
|
(C++17) | P0220R1 |
__cpp_lib_array_
|
Constexpr for std::reverse_iterator, std::move_iterator, std::array and range access | 201603L
|
(C++17) | P0031R0 |
| ConstexprIterator; constexpr comparison for std::array; misc constexpr bits (std::array::fill et al.) | 201811L
|
(C++20) | P0858R0 LWG3257 P1023R0 P1032R1 | |
__cpp_lib_as_const
|
std::as_const | 201510L
|
(C++17) | P0007R1 |
__cpp_lib_associative_
|
Heterogeneous erasure in associative containers and unordered associative containers | 202110L
|
(C++23) | P2077R3 |
__cpp_lib_associative_
|
Heterogeneous overloads for the remaining member functions in ordered and unordered associative containers | 202306L
|
(C++26) | P2363R5 |
__cpp_lib_assume_
|
std::assume_aligned | 201811L
|
(C++20) | P1007R3 |
__cpp_lib_atomic_
|
std::atomic_flag::test | 201907L
|
(C++20) | P1135R6 |
__cpp_lib_atomic_
|
Floating-point atomic | 201711L
|
(C++20) | P0020R6 |
__cpp_lib_atomic_
|
Constexpr std::atomic<T>::is_always_lock_free | 201603L
|
(C++17) | P0152R1 |
__cpp_lib_atomic_
|
Atomic lockfree integral types (std::atomic_signed_lock_free, std::atomic_unsigned_lock_free) | 201907L
|
(C++20) | P1135R6 |
__cpp_lib_atomic_
|
Atomic minimum/maximum (std::atomic::fetch_min, std::atomic::fetch_max, etc) | 202403L
|
(C++26) | P0493R5 |
__cpp_lib_atomic_
|
std::atomic_ref | 201806L
|
(C++20) | P0019R8 |
| std::atomic_ref::address() | 202411L
|
(C++26) | P2835R7 | |
__cpp_lib_atomic_
|
std::atomic<std::shared_ptr> | 201711L
|
(C++20) | P0718R2 |
__cpp_lib_atomic_
|
Fixing atomic initialization (value-initialize std::atomic by default) | 201911L
|
(C++20) | P0883R2 |
__cpp_lib_atomic_
|
Efficient std::atomic waiting | 201907L
|
(C++20) | P1135R6 |
__cpp_lib_barrier
|
std::barrier | 201907L
|
(C++20) | P1135R6 |
| std::barrier's phase completion guarantees | 202302L
|
(C++23) | P2588R3 | |
__cpp_lib_bind_back
|
std::bind_back | 202202L
|
(C++23) | P2387R3 |
| Allow passing callable objects as non-type template arguments to std::bind_back | 202306L
|
(C++26) | P2714R1 | |
__cpp_lib_bind_front
|
std::bind_front | 201907L
|
(C++20) | P0356R5 P1651R0 |
| Allow passing callable objects as non-type template arguments to std::bind_front | 202306L
|
(C++26) | P2714R1 | |
__cpp_lib_bit_cast
|
std::bit_cast | 201806L
|
(C++20) | P0476R2 |
__cpp_lib_bitops
|
Bit operations | 201907L
|
(C++20) | P0553R4 |
__cpp_lib_bitset
|
Interfacing std::bitset with std::string_view | 202306L
|
(C++26) | P2697R1 |
__cpp_lib_bool_constant
|
std::bool_constant | 201505L
|
(C++17) | N4389 |
__cpp_lib_bounded_
|
std::is_bounded_array, std::is_unbounded_array | 201902L
|
(C++20) | P1357R1 |
__cpp_lib_boyer_
|
Searchers | 201603L
|
(C++17) | P0220R1 |
__cpp_lib_byte
|
std::byte | 201603L
|
(C++17) | P0298R3 |
__cpp_lib_byteswap
|
std::byteswap | 202110L
|
(C++23) | P1272R4 |
__cpp_lib_char8_
|
Library support for char8_t
|
201907L
|
(C++20) | P0482R6 P1423R3 |
__cpp_lib_chrono
|
Rounding functions for std::chrono::duration and std::chrono::time_point | 201510L
|
(C++17) | P0092R1 |
| Constexpr for all the member functions of std::chrono::duration and std::chrono::time_point | 201611L
|
P0505R0 | ||
| Calendars and Time zones | 201907L
|
(C++20) | P0355R7 P1466R3 | |
| Hashing support for std::chrono value classes | 202306L
|
(C++26) | P2592R3 | |
__cpp_lib_chrono_
|
User-defined literals for time types |