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 |