| Doc. No.: | P0941R0 |
|---|---|
| Date: | 2018-05-04 |
| Reply to: | Ville Voutilainen |
| Audience: | EWG, LEWG |
This revision of this paper proposes incorporating feature-testing macros into the working draft of the C++ standard.
At the November 2017 (Albuquerque) meeting of WG21, there was a five-way poll of all of the C++ experts in attendance concerning their support for "Feature macros should be standardized in the IS, and we want to invite a proposal to be reviewed by EWG to discss the rationale and granularity." The results of the poll:
| Strongly favor | Favor | Neutral | Oppose | Strongly oppose |
|---|---|---|---|---|
| 27 | 21 | 9 | 4 | 1 |
The approach taken here is as follows:
__has_cpp_attributeAfter [lex.literal], insert a new subsection of section [lex] with the following content:
- has-attribute-expression:
__has_cpp_attribute (attribute-token)A has-attribute-expression shall appear only in the controlling constant expression of a
#ifor#elifdirective ([cpp.cond] 16.1). The has-attribute-expression is replaced by a non-zero pp-number if the implementation supports an attribute with the specified name, and by the pp-number 0 otherwise.For a standard attribute, the value of the
__has_cpp_attributemacro is based on the year and month in which the attribute was voted into the working draft. In the case where the attribute is vendor-specific, the value is implementation-defined. However, in most cases it is expected that the availability of an attribute can be detected by any non-zero result.The
#ifdefand#ifndefdirectives, and thedefinedconditional inclusion operator, shall treat__has_cpp_attributeas if it were the name of a defined macro. The identifier__has_cpp_attributeshall not appear in any context not mentioned in this section.This demonstrates a way to use the attribute
[[deprecated]]only if it is available.#ifndef __has_cpp_attribute # define __has_cpp_attribute(x) 0 #endif #if __has_cpp_attribute(deprecated) # define ATTR_DEPRECATED(msg) [[deprecated(msg)]] #else # define ATTR_DEPRECATED(msg) #endif
Drafting note: these are intended to match the latest values in SD-6. Wording review should check that that is indeed so.
After [support.runtime], insert a new subsection of section [language.support] with the following content:
The macros that are not predefined are defined in the header <version> in addition to the header specified in the table.
Macro name Value Header __cpp_unicode_characters200704 predefined __cpp_raw_strings200710 predefined __cpp_unicode_literals200710 predefined __cpp_user_defined_literals200809 predefined __cpp_threadsafe_static_init200806 predefined __cpp_lambdas200907 predefined __cpp_range_based_for200907 predefined __cpp_static_assert200410 predefined __cpp_decltype200707 predefined __cpp_attributes200809 predefined __has_cpp_attribute(noreturn)200809 predefined __has_cpp_attribute(carries_dependency)200809 predefined __cpp_rvalue_references200610 predefined __cpp_variadic_templates200704 predefined __cpp_initializer_lists200806 predefined __cpp_delegating_constructors200604 predefined __cpp_nsdmi200809 predefined __cpp_ref_qualifiers200710 predefined __cpp_alias_templates200704 predefined __cpp_binary_literals201304 predefined __cpp_init_captures201304 predefined __cpp_generic_lambdas201304 predefined __cpp_sized_deallocation201309 predefined __cpp_decltype_auto201304 predefined __cpp_return_type_deduction201304 predefined __has_cpp_attribute(deprecated)201309 predefined __cpp_aggregate_nsdmi201304 predefined __cpp_variable_templates201304 predefined __cpp_lib_integer_sequence201304 <utility>__cpp_lib_exchange_function201304 <utility>__cpp_lib_tuples_by_type201304 <utility>__cpp_lib_tuple_element_t201402 <utility>__cpp_lib_make_unique201304 <memory>__cpp_lib_transparent_operators201210 <functional>__cpp_lib_integral_constant_callable201304 <type_traits>__cpp_lib_transformation_trait_aliases201304 <type_traits>__cpp_lib_result_of_sfinae201210 <functional>
<type_traits>__cpp_lib_is_final201402 <type_traits>__cpp_lib_is_null_pointer201309 <type_traits>__cpp_lib_string_udls201304 <string>__cpp_lib_generic_associative_lookup201304 <map>
<set>__cpp_lib_null_iterators201304 <iterator>__cpp_lib_make_reverse_iterator201402 <iterator>__cpp_lib_robust_nonmodifying_seq_ops201304 <algorithm>__cpp_lib_complex_udls201309 <complex>__cpp_lib_quoted_string_io201304 <iomanip>__has_include(<shared_mutex>)1 predefined __cpp_lib_shared_timed_mutex201402 <shared_mutex>__cpp_hex_float201603 predefined __cpp_inline_variables201606 predefined __cpp_aligned_new201606 predefined __cpp_guaranteed_copy_elision201606 predefined __cpp_noexcept_function_type201510 predefined __cpp_fold_expressions201411 predefined __cpp_capture_star_this201603 predefined __cpp_constexpr201603 predefined __cpp_if_constexpr201606 predefined __cpp_range_based_for201603 predefined __cpp_static_assert201411 predefined __cpp_deduction_guides201606 predefined __cpp_deduction_guides201611 predefined __cpp_nontype_template_parameter_auto201606 predefined __cpp_namespace_attributes201411 predefined __cpp_enumerator_attributes201411 predefined __cpp_inheriting_constructors201511 predefined __cpp_variadic_using201611 predefined __has_cpp_attribute(fallthrough)201603 predefined __has_cpp_attribute(nodiscard)201603 predefined __has_cpp_attribute(maybe_unused)201603 predefined __cpp_structured_bindings201606 predefined __cpp_aggregate_bases201603 predefined __cpp_nontype_template_args201411 predefined __cpp_template_template_args201611 predefined __cpp_fold_expressions201603 predefined __has_includedefined predefined __cpp_lib_byte201603 <cstddef>__cpp_lib_hardware_interference_size201703 <new>__cpp_lib_launder201606 <new>__cpp_lib_uncaught_exceptions201411 <exception>__cpp_lib_as_const201510 <utility>__cpp_lib_make_from_tuple201606 <tuple>__cpp_lib_apply201603 <tuple>__has_include(<optional>)1 predefined __cpp_lib_optional201603 <optional>__has_include(<any>)1 predefined __cpp_lib_any201603 <any>__has_include(<memory_resource>)1 predefined __cpp_lib_memory_resource201603 <memory_resource>__cpp_lib_boyer_moore_searcher201603 <functional>__has_include(<string_view>)1 predefined __cpp_lib_string_view201603 <string_view>__cpp_lib_sample201603 <algorithm>__cpp_lib_any201606 <any>__cpp_lib_optional201606 <optional>__cpp_lib_optional201606 <optional>__has_include(<variant>)1 predefined __cpp_lib_variant201606 <variant>__cpp_lib_addressof_constexpr201603 <memory>__cpp_lib_raw_memory_algorithms201606 <memory>__cpp_lib_transparent_operators201510 <memory> <functional>__cpp_lib_enable_shared_from_this201603 <memory>__cpp_lib_shared_ptr_weak_type201606 <memory>__cpp_lib_shared_ptr_arrays201611 <memory>__cpp_lib_invoke201411 <functional>__cpp_lib_not_fn201603 <functional>__cpp_lib_void_t201411 <type_traits>__cpp_lib_bool_constant201505 <type_traits>__cpp_lib_type_trait_variable_templates201510 <type_traits>__cpp_lib_logical_traits201510 <type_traits>__cpp_lib_is_swappable201603 <type_traits>__cpp_lib_is_invocable201703 <type_traits>__cpp_lib_has_unique_object_representations201606 <type_traits>__cpp_lib_is_aggregate201703 <type_traits>__cpp_lib_chrono201611 <chrono>__has_include(<execution>)1 predefined __cpp_lib_execution201603 <execution>__cpp_lib_parallel_algorithm201603 <algorithm><numeric>__cpp_lib_to_chars201611 <utility>__cpp_lib_string_view201606 <string> <string_view>__cpp_lib_allocator_traits_is_always_equal201411 <memory><scoped_allocator>
<string><deque>
<forward_list><list>
<vector><map>
<set><unordered_map>
<unordered_set>__cpp_lib_incomplete_container_elements201505 <forwardlist>
<list> <vector>__cpp_lib_map_try_emplace201411 <map>__cpp_lib_unordered_map_try_emplace201411 <unordered_map>__cpp_lib_node_extract201606 <map> <set> <unordered_map> <unordered_set>__cpp_lib_array_constexpr201603 <iterator> <array>__cpp_lib_nonmember_container_access201411 <iterator> <array> <deque> <forward_list>
<list> <map> <regex> <set> <string>
<unordered_map> <unordered_set> <vector>__cpp_lib_clamp201603 <algorithm>__cpp_lib_gcd_lcm201606 <numeric>__cpp_lib_hypot201603 <cmath>__cpp_lib_math_special_functions201603 <cmath>__has_include(<filesystem>)1 predefined __cpp_lib_filesystem201703 <filesystem>__cpp_lib_atomic_is_always_lock_free201603 <atomic>__cpp_lib_shared_mutex201505 <shared_mutex>__cpp_lib_scoped_lock201703 <mutex>
With very few exceptions, the features of C++98 have all been implemented in virtually every C++ compiler. But in many compilers, some of them can be enabled/disabled. It is recommended that the macros in the following table should be used to indicate whether one of these features is enabled in the current compilation.
| Macro name | Value | Header |
|---|---|---|
__cpp_rtti |
199711 | predefined |
__cpp_exceptions |
199711 | predefined |
| Date | Document | Description |
|---|---|---|
| P0941R0 | Initial draft | |
| P0941R1 | Draft wording, with non-standard content removed and rtti/exception macros made a separate point looking for feedback. |