Feature testing (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 presence of an attribute.
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 |
---|---|---|---|
assert |
[[assert]] |
201806L | (C++20) |
carries_dependency |
[[carries_dependency]] |
200809L | (C++11) |
deprecated |
[[deprecated]] |
201309L | (C++14) |
ensures |
[[ensures]] |
201806L | (C++20) |
expects |
[[expects]] |
201806L | (C++20) |
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) |
noreturn |
[[noreturn]] |
200809L | (C++11) |
unlikely |
[[unlikely]] |
201803L | (C++20) |
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 | Extension to aggregate initialization | 201603L | (C++17) |
__cpp_aggregate_nsdmi | Member initializers and aggregates | 201304L | (C++14) |
__cpp_aggregate_paren_init | Aggregate initialization in the form of direct initialization | 201902L | (C++20) |
__cpp_alias_templates | Template aliases | 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 in the C++ core language | 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_conditional_explicit | explicit(bool) | 201806L | (C++20) |
__cpp_constexpr
| constexpr | 200704L | (C++11) |
Relaxing constraints on constexpr functions / constexpr member functions and implicit const
| 201304L | (C++14) | |
Constexpr lambda | 201603L | (C++17) | |
__cpp_coroutines | Coroutines | 201902L | (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) |
__cpp_delegating_constructors | Delegating constructors | 200604L | (C++11) |
__cpp_enumerator_attributes | Attributes for enumerators | 201411L | (C++17) |
__cpp_fold_expressions | Fold expressions | 201603L | (C++17) |
__cpp_generic_lambdas | Generic (polymorphic) lambda expressions | 201304L | (C++14) |
__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_destroying_delete | Destroying operator delete (compiler support) | 201806L | (C++20) |
__cpp_impl_three_way_comparison | Three-way comparison (compiler support) | 201711L | (C++20) |
__cpp_inheriting_constructors
| Inheriting constructors | 200802L | (C++11) |
Rewording inheriting constructors | 201511L | (C++17) | |
__cpp_init_captures | Generalized lambda-capture | 201304L | (C++14) |
__cpp_initializer_lists | Initializer lists | 200806L | (C++11) |
__cpp_inline_variables | Inline variables | 201606L | (C++17) |
__cpp_lambdas | Lambda expressions | 200907L | (C++11) |
__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) |
__cpp_nontype_template_ parameter_auto
| Declaring non-type template parameters with auto
| 201606L | (C++17) |
__cpp_nontype_template_ parameter_class
| Class types in non-type template parameters | 201806L | (C++20) |
__cpp_nsdmi | Non-static data member initializers | 200809L | (C++11) |
__cpp_range_based_for
| Range-based for loop | 200907L | (C++11) |
Generalized range-based for loop | 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) |
Extended 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_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) |
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 | Adding constexpr modifiers to std::reverse_iterator , std::move_iterator , std::array and range access
| 201603L |
<iterator> <array>
| (C++17) |
__cpp_lib_as_const | std::as_const | 201510L | <utility> | (C++17) |
__cpp_lib_atomic_ is_always_lock_free
| constexpr atomic<T>::is_always_lock_free | 201603L | <atomic> | (C++17) |
__cpp_lib_atomic_ref | std::atomic_ref | 201806L | <atomic> | (C++20) |
__cpp_lib_bind_front | std::bind_front | 201811L | <functional> | (C++20) |
__cpp_lib_bit_cast | std::bit_cast | 201806L | <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 | A byte type definition | 201603L | <cstddef> | (C++17) |
__cpp_lib_char8_t | library support for char8_t |
201811L | <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) |
making all the member functions of std::chrono::duration and std::chrono::time_point constexpr | 201611L | <chrono> | (C++17) | |
__cpp_lib_chrono_udls | User-defined literals for time types | 201304L | <chrono> | (C++14) |
__cpp_lib_clamp | An algorithm to "clamp" a value between a pair of boundary values (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 | 201806L | <concepts> | (C++20) |
__cpp_lib_constexpr_misc | Constexpr for miscellaneous facilities | 201811L |
<array> <functional> <iterator> <string_view> <tuple> <utility> | (C++20) |
__cpp_lib_constexpr_ swap_algorithms
| Constexpr for swap and swap related functions | 201806L | <algorithm> | (C++20) |
__cpp_lib_destroying_delete | Destroying operator delete (library support) | 201806L | <new> | (C++20) |
__cpp_lib_enable_ shared_from_this
| Re-enabling shared_from_this | 201603L | <memory> | (C++17) |
__cpp_lib_erase_if | Uniform container erasure | 201811L |
<string> <deque> <forward_list> <list> <vector> <map> <set> <unordered_map> <unordered_set>
| (C++20) |
__cpp_lib_exchange_function | exchange() utility function | 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_gcd_lcm |
std::gcd , std::lcm
| 201606L | <numeric> | (C++17) |
__cpp_lib_generic_ associative_lookup
| Adding heterogeneous comparison lookup to associative containers | 201304L |
<map> <set>
| (C++14) |
__cpp_lib_generic_ unordered_lookup
| Adding heterogeneous comparison lookup to unordered associative containers | 201811L |
<unordered_map> <unordered_set>
| (C++20) |
__cpp_lib_generic_ unordered_hash_lookup
| Adding pre-calculated hash value lookup to unordered associative containers | 201902L |
<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_integer_sequence | Compile-time integer sequences | 201304L | <utility> | (C++14) |
__cpp_lib_interpolate |
std::lerp() , std::midpoint()
| 201902L |
<cmath> <numeric>
| (C++20) |
__cpp_lib_integral_ constant_callable
| std::integral_constant::operator() | 201304L | <type_traits> | (C++14) |
__cpp_lib_invoke |
std::invoke function template | 201411L | <functional> | (C++17) |
__cpp_lib_is_aggregate |
std::is_aggregate type trait | 201703L | <type_traits> | (C++17) |
__cpp_lib_is_constant_evaluated | Constant-evaluated context detection (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_null_pointer | std::is_null_pointer | 201309L | <type_traits> | (C++14) |
__cpp_lib_is_swappable | [nothrow-]swappable traits | 201603L | <type_traits> | (C++17) |
__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 : apply for construction | 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_ 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
| Non-member size() and more (uniform container access) | 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 | Adopt the Parallelism TS for C++17 | 201603L |
<algorithm> <numeric>
| (C++17) |
__cpp_lib_quoted_string_io | std::quoted | 201304L | <iomanip> | (C++14) |
__cpp_lib_ranges | Ranges library and constrained algorithms | 201811L |
<algorithm> <functional> <iterator> <memory> <ranges>
| (C++20) |
__cpp_lib_ raw_memory_algorithms
| Extending memory management tools | 201606L | <memory> | (C++17) |
__cpp_lib_result_of_sfinae |
std::result_of and SFINAE | 201210L |
<functional> <type_traits>
| (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 | Variadic std::lock_guard (std::scoped_lock ) | 201703L | <mutex> | (C++17) |
__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) |
__cpp_lib_shared_ptr_weak_type | shared_ptr::weak_type | 201606L | <memory> | (C++17) |
__cpp_lib_shared_timed_mutex | Rename shared_mutex to shared_timed_mutex
| 201402L | <shared_mutex> | (C++14) |
__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) |
__cpp_lib_three_way_comparison | Three-way comparison (library support) | 201711L | <compare> | (C++20) |
__cpp_lib_to_chars | Elementary string conversions (std::to_chars , std::from_chars ) | 201611L | <charconv> | (C++17) |
__cpp_lib_transformation_ trait_aliases
| TransformationTraits Redux | 201304L | <type_traits> | (C++14) |
__cpp_lib_ transparent_operators
| Transparent operator functors (std::less<> et al) | 201210L | <functional> | (C++14) |
Making std::owner_less more flexible (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 |
<utility> <tuple>
| (C++14) |
__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_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) |
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() { }
See Also
Standing Document 6 | The official document on Feature Test Recommendations |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
http://en.cppreference.com/w/cpp/feature_test