Feature Test Recommendations (C++20)
To track progress of partial implementation of C++ standards and experimental features, the feature test recommendations provide a set of preprocessor macros which, if defined by the implementation, give a simple and portable way to detect the presence of said features.
Function Macros
Feature test function macros can be expanded in the expression of #if and #elif. They will be treated as defined macros by #ifdef, #ifndef and defined but cannot be used anywhere else.
Finding Headers
__has_include( header-name )
|
(1) | ||||||||
Perform a check on the header file name in the same way a #include directive would interpret it.
If the header is found, it expands to 1
, 0
otherwise.
Note: __has_include is part of C++17.
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, the presence of vendor-specific attributes is determined by a non-zero value.
Language and Library Features
The following macros expand to a numeric value corresponding to the year and month when the feature has been included in the working draft.
When a feature changes significantly, the macro will be updated accordingly.
Macro name | Feature | Value | Header | Standard/TS |
---|---|---|---|---|
__cpp_aggregate_bases | Extension to aggregate initialization | 201603 | predefined | (C++17) |
__cpp_aggregate_nsdmi | Member initializers and aggregates | 201304 | predefined | (C++14) |
__cpp_alias_templates | Template aliases | 200704 | predefined | (C++11) |
__cpp_aligned_new | Dynamic memory allocation for over-aligned data | 201606 | predefined | (C++17) |
__cpp_attributes | Attributes | 200809 | predefined | (C++11) |
__cpp_binary_literals | Binary literals in the C++ core language | 201304 | predefined | (C++14) |
__cpp_capture_star_this | Lambda capture of *this by value as [=,*this] | 201603 | predefined | (C++17) |
__cpp_concepts | Constraints and concepts | 201507 | predefined | (concepts TS) |
__cpp_constexpr | constexpr | 200704 | predefined | (C++11) |
Relaxing constraints on constexpr functions / constexpr member functions and implicit const | 201304 | predefined | (C++14) | |
Constexpr lambda | 201603 | predefined | (C++17) | |
__cpp_decltype | decltype | 200707 | predefined | (C++11) |
__cpp_decltype_auto | Return type deduction for normal functions | 201304 | predefined | (C++14) |
__cpp_deduction_guides | Template argument deduction for class templates | 201703 | predefined | (C++17) |
__cpp_delegating_constructors | Delegating constructors | 200604 | predefined | (C++11) |
__cpp_enumerator_attributes | Attributes for enumerators | 201411 | predefined | (C++17) |
__cpp_exceptions | Exception handling | 199711 | predefined | (c++98) |
__cpp_explicit_bool | explicit(bool) |
201806 | predefined | (c++20) |
__cpp_fold_expressions | Fold expressions | 201603 | predefined | (C++17) |
__cpp_generic_lambdas | Generic (polymorphic) lambda expressions | 201304 | predefined | (C++14) |
__cpp_guaranteed_copy_elision | Guaranteed copy elision through simplified value categories | 201606 | predefined | (C++17) |
__cpp_hex_float | Hexadecimal floating literals | 201603 | predefined | (C++17) |
__cpp_if_constexpr | constexpr if | 201606 | predefined | (C++17) |
__cpp_inheriting_constructors | Inheriting constructors | 200802 | predefined | (C++11) |
Rewording inheriting constructors | 201511 | predefined | (C++17) | |
__cpp_init_captures | Generalized lambda-capture | 201304 | predefined | (C++14) |
__cpp_initializer_lists | Initializer lists | 200806 | predefined | (C++11) |
__cpp_inline_variables | Inline variables | 201606 | predefined | (C++17) |
__cpp_lambdas | Lambda expressions | 200907 | predefined | (C++11) |
__cpp_lib_addressof_constexpr | constexpr std::addressof | 201603 | <memory> | (C++17) |
__cpp_lib_allocator_traits_is_always_equal | std::allocator_traits::is_always_equal | 201411 | <memory> <scoped_allocator> <string> <deque> <forward_list> <list> <vector> <map> <set> <unordered_map> <unordered_set> | (C++17) |
__cpp_lib_any | std::any | 201606 | <any> | (C++17) |
__cpp_lib_apply | std::apply | 201603 | <tuple> | (C++17) |
__cpp_lib_array_constexpr | Adding constexpr modifiers to std::reverse_iterator, std::move_iterator, std::array and range access | 201603 | <iterator> <array> | (C++17) |
__cpp_lib_as_const | std::as_const | 201510 | <utility> | (C++17) |
__cpp_lib_atomic_is_always_lock_free | constexpr atomic<T>::is_always_lock_free | 201603 | <atomic> | (C++17) |
__cpp_lib_atomic_ref | std::atomic_ref | 201806 | <atomic> | (C++20) |
__cpp_lib_bit_cast | std::bit_cast | 201806 | <bit> | (C++20) |
__cpp_lib_bool_constant | std::bool_constant | 201505 | <type_traits> | (C++17) |
__cpp_lib_boyer_moore_searcher | Searchers | 201603 | <functional> | (C++17) |
__cpp_lib_byte | A byte type definition | 201603 | <cstddef> | (C++17) |
__cpp_lib_chrono | rounding functions for std::chrono::duration and std::chrono::time_point | 201510 | <chrono> | (C++17) |
making all the member functions of std::chrono::duration and std::chrono::time_point constexpr | 201611 | <chrono> | (C++17) | |
__cpp_lib_chrono_udls | User-defined literals for time types | 201304 | <chrono> | (C++14) |
__cpp_lib_clamp | An algorithm to "clamp" a value between a pair of boundary values (std::clamp) | 201603 | <algorithm> | (C++17) |
__cpp_lib_complex_udls | User-defined Literals for std::complex | 201309 | <complex> | (C++14) |
__cpp_lib_concepts | Standard library concepts | 201806 | <concepts> | (C++20) |
__cpp_lib_constexpr_swap_algorithms | Constexpr for swap and swap related functions | 201806 | <algorithm> | (C++20) |
__cpp_lib_enable_shared_from_this | Re-enabling shared_from_this | 201603 | <memory> | (C++17) |
__cpp_lib_exchange_function | exchange() utility function | 201304 | <utility> | (C++14) |
__cpp_lib_execution | Execution policies | 201603 | <execution> | (C++17) |
__cpp_lib_experimental_any | class any | 201411 | <experimental/any> | (library fundamentals TS) |
__cpp_lib_experimental_apply | apply() call a function with arguments from a tuple | 201402 | <experimental/tuple> | (library fundamentals TS) |
__cpp_lib_experimental_boyer_moore_searching | Extending std::search to use Additional Searching Algorithms | 201411 | <experimental/functional> | (library fundamentals TS) |
__cpp_lib_experimental_filesystem | File System TS | 201406 | <experimental/filesystem> | (filesystem TS) |
__cpp_lib_experimental_function_erased_allocator | Type-erased allocator for std::function | 201406 | <experimental/functional> | (library fundamentals TS) |
__cpp_lib_experimental_invocation_type | Invocation type traits | 201406 | <experimental/type_traits> | (library fundamentals TS) |
__cpp_lib_experimental_memory_resources | Polymorphic Memory Resources | 201402 | <experimental/memory_resource> | (library fundamentals TS) |
__cpp_lib_experimental_optional | optional objects | 201411 | <experimental/optional> | (library fundamentals TS) |
__cpp_lib_experimental_packaged_task_erased_allocator | Type-erased allocator for std::packaged_task | 201406 | <experimental/future> | (library fundamentals TS) |
__cpp_lib_experimental_parallel_algorithm | Extensions for parallelism | 201505 | <experimental/algorithm> <experimental/exception_list> <experimental/execution_policy> <experimental/numeric> | (parallelism TS) |
__cpp_lib_experimental_promise_erased_allocator | Type-erased allocator for std::promise | 201406 | <experimental/future> | (library fundamentals TS) |
__cpp_lib_experimental_sample | sample | 201402 | <experimental/algorithm> | (library fundamentals TS) |
__cpp_lib_experimental_shared_ptr_arrays | Extending shared_ptr to Support Arrays | 201406 | <experimental/memory> | (library fundamentals TS) |
__cpp_lib_experimental_string_view | string_view: a non-owning reference to a string | 201411 | <experimental/string_view> | (library fundamentals TS) |
__cpp_lib_experimental_type_trait_variable_templates | Variable templates For type traits | 201402 | <experimental/type_traits> | (library fundamentals TS) |
__cpp_lib_filesystem | Filesystem library | 201703 | <filesystem> | (C++17) |
__cpp_lib_gcd_lcm | std::gcd, std::lcm | 201606 | <numeric> | (C++17) |
__cpp_lib_generic_associative_lookup | Adding heterogeneous comparison lookup to associative containers | 201304 | <map> <set> | (C++14) |
__cpp_lib_hardware_interference_size | constexpr std::hardware_{constructive, destructive}_interference_size | 201703 | <new> | (C++17) |
__cpp_lib_has_unique_object_representations | std::has_unique_object_representations | 201606 | <type_traits> | (C++17) |
__cpp_lib_hypot | 3-argument overload of std::hypot | 201603 | <cmath> | (C++17) |
__cpp_lib_incomplete_container_elements | Minimal incomplete type support for standard containers | 201505 | <forward_list> <list> <vector> | (C++17) |
__cpp_lib_integer_sequence | Compile-time integer sequences | 201304 | <utility> | (C++14) |
__cpp_lib_integral_constant_callable | std::integral_constant::operator() | 201304 | <type_traits> | (C++14) |
__cpp_lib_invoke | std::invoke function template | 201411 | <functional> | (C++17) |
__cpp_lib_is_aggregate | std::is_aggregate type trait | 201703 | <type_traits> | (C++17) |
__cpp_lib_is_final | std::is_final | 201402 | <type_traits> | (C++14) |
__cpp_lib_is_invocable | std::is_invocable, std::invoke_result | 201703 | <type_traits> | (C++17) |
__cpp_lib_is_null_pointer | std::is_null_pointer | 201309 | <type_traits> | (C++14) |
__cpp_lib_is_swappable | [nothrow-]swappable traits | 201603 | <type_traits> | (C++17) |
__cpp_lib_launder | Core Issue 1776: Replacement of class objects containing reference members (std::launder) | 201606 | <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 | 201806 | <forward_list> <list> | (C++20) |
__cpp_lib_logical_traits | Logical operator type traits | 201510 | <type_traits> | (C++17) |
__cpp_lib_make_from_tuple | make_from_tuple: apply for construction | 201606 | <tuple> | (C++17) |
__cpp_lib_make_reverse_iterator | std::make_reverse_iterator | 201402 | <iterator> | (C++14) |
__cpp_lib_make_unique | std::make_unique | 201304 | <memory> | (C++14) |
__cpp_lib_map_try_emplace | std::map::try_emplace, std::map::insert_or_assign | 201411 | <map> | (C++17) |
__cpp_lib_math_special_functions | Mathematical special functions for C++17 | 201603 | <cmath> | (C++17) |
__cpp_lib_memory_resource | std::pmr::memory_resource | 201603 | <memory_resource> | (C++17) |
__cpp_lib_node_extract | Splicing maps and sets (std::map::extract, std::map::merge, std::map::insert(node_type), etc) | 201606 | <map> <set> <unordered_map> <unordered_set> | (C++17) |
__cpp_lib_nonmember_container_access | Non-member size() and more (uniform container access) |
201411 | <iterator> <array> <deque> <forward_list> <list> <map> <regex> <set> <string> <unordered_map> <unordered_set> <vector> | (C++17) |
__cpp_lib_not_fn | std::not_fn | 201603 | <functional> | (C++17) |
__cpp_lib_null_iterators | Null ForwardIterators | 201304 | <iterator> | (C++14) |
__cpp_lib_optional | std::optional | 201606 | <optional> | (C++17) |
__cpp_lib_parallel_algorithm | Adopt the Parallelism TS for C++17 | 201603 | <algorithm> <numeric> | (C++17) |
__cpp_lib_quoted_string_io | std::quoted | 201304 | <iomanip> | (C++14) |
__cpp_lib_raw_memory_algorithms | Extending memory management tools | 201606 | <memory> | (C++17) |
__cpp_lib_result_of_sfinae | std::result_of and SFINAE | 201210 | <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) | 201304 | <algorithm> | (C++14) |
__cpp_lib_sample | std::sample | 201603 | <algorithm> | (C++17) |
__cpp_lib_scoped_lock | Variadic std::lock_guard (std::scoped_lock) | 201703 | <mutex> | (C++17) |
__cpp_lib_shared_mutex | std::shared_mutex (untimed) | 201505 | <shared_mutex> | (C++17) |
__cpp_lib_shared_ptr_arrays | std::shared_ptr<T[]> | 201611 | <memory> | (C++17) |
__cpp_lib_shared_ptr_weak_type | shared_ptr::weak_type | 201606 | <memory> | (C++17) |
__cpp_lib_shared_timed_mutex | Rename shared_mutex to shared_timed_mutex |
201402 | <shared_mutex> | (C++14) |
__cpp_lib_string_udls | User-defined literals for string types | 201304 | <string> | (C++14) |
__cpp_lib_string_view | std::string_view | 201606 | <string> <string_view> | (C++17) |
__cpp_lib_to_chars | Elementary string conversions (std::to_chars, std::from_chars) | 201611 | <utility> | (C++17) |
__cpp_lib_transformation_trait_aliases | TransformationTraits Redux | 201304 | <type_traits> | (C++14) |
__cpp_lib_transparent_operators | Making Operator Functors greater<> | 201210 | <functional> | (C++14) |
Making std::owner_less more flexible (std::owner_less<void>) | 201510 | <memory> <functional> | (C++17) | |
__cpp_lib_tuple_element_t | std::tuple_element_t | 201402 | <tuple> | (C++14) |
__cpp_lib_tuples_by_type | Addressing tuples by type | 201304 | <utility> <tuple> | (C++14) |
__cpp_lib_type_trait_variable_templates | Type traits variable templates (std::is_void_v, etc) | 201510 | <type_traits> | (C++17) |
__cpp_lib_uncaught_exceptions | std::uncaught_exceptions | 201411 | <exception> | (C++17) |
__cpp_lib_unordered_map_try_emplace | std::unordered_map::try_emplace, std::unordered_map::insert_or_assign | 201411 | <unordered_map> | (C++17) |
__cpp_lib_variant | std::variant: a type-safe union for C++17 | 201606 | <variant> | (C++17) |
__cpp_lib_void_t | std::void_t | 201411 | <type_traits> | (C++17) |
__cpp_namespace_attributes | Attributes for namespaces | 201411 | predefined | (C++17) |
__cpp_noexcept_function_type | Make exception specifications be part of the type system | 201510 | predefined | (C++17) |
__cpp_nontype_template_args | Allow constant evaluation for all non-type template arguments | 201411 | predefined | (C++17) |
__cpp_nontype_template_parameter_auto | Declaring non-type template parameters with auto | 201606 | predefined | (C++17) |
__cpp_nontype_template_parameter_class | Class types in non-type template parameters | 201806 | predefined | (C++20) |
__cpp_nsdmi | Non-static data member initializers | 200809 | predefined | (C++11) |
__cpp_range_based_for | Range-based for loop | 200907 | predefined | (C++11) |
Generalized range-based for loop | 201603 | predefined | (C++17) | |
__cpp_raw_strings | Raw string literals | 200710 | predefined | (C++11) |
__cpp_ref_qualifiers | ref-qualifiers | 200710 | predefined | (C++11) |
__cpp_return_type_deduction | Return type deduction for normal functions | 201304 | predefined | (C++14) |
__cpp_rtti | Run-time type identification (dynamic_cast, typeid) | 199711 | predefined | (c++98) |
__cpp_rvalue_references | Rvalue reference | 200610 | predefined | (C++11) |
__cpp_sized_deallocation | Sized deallocation | 201309 | predefined | (C++14) |
__cpp_static_assert | static_assert | 200410 | predefined | (C++11) |
Extended static_assert |
201411 | predefined | (C++17) | |
__cpp_structured_bindings | structured bindings | 201606 | predefined | (C++17) |
__cpp_template_template_args | Matching of template template-arguments | 201611 | predefined | (C++17) |
__cpp_threadsafe_static_init | Dynamic initialization and destruction with concurrency | 200806 | predefined | (C++11) |
__cpp_transactional_memory | Transactional Memory | 201505 | predefined | (TM TS) |
__cpp_unicode_characters | New character types (char16_t and char32_t) | 200704 | predefined | (C++11) |
__cpp_unicode_literals | Unicode string literals | 200710 | predefined | (C++11) |
__cpp_user_defined_literals | User-defined literals | 200809 | predefined | (C++11) |
__cpp_variable_templates | Variable templates | 201304 | predefined | (C++14) |
__cpp_variadic_templates | Variadic templates | 200704 | predefined | (C++11) |
__cpp_variadic_using | Pack expansions in using-declarations | 201611 | predefined | (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 |