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_attribute
After [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
#if
or#elif
directive ([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_attribute
macro 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
#ifdef
and#ifndef
directives, and thedefined
conditional inclusion operator, shall treat__has_cpp_attribute
as if it were the name of a defined macro. The identifier__has_cpp_attribute
shall 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_characters
200704 predefined __cpp_raw_strings
200710 predefined __cpp_unicode_literals
200710 predefined __cpp_user_defined_literals
200809 predefined __cpp_threadsafe_static_init
200806 predefined __cpp_lambdas
200907 predefined __cpp_range_based_for
200907 predefined __cpp_static_assert
200410 predefined __cpp_decltype
200707 predefined __cpp_attributes
200809 predefined __has_cpp_attribute(noreturn)
200809 predefined __has_cpp_attribute(carries_dependency)
200809 predefined __cpp_rvalue_references
200610 predefined __cpp_variadic_templates
200704 predefined __cpp_initializer_lists
200806 predefined __cpp_delegating_constructors
200604 predefined __cpp_nsdmi
200809 predefined __cpp_ref_qualifiers
200710 predefined __cpp_alias_templates
200704 predefined __cpp_binary_literals
201304 predefined __cpp_init_captures
201304 predefined __cpp_generic_lambdas
201304 predefined __cpp_sized_deallocation
201309 predefined __cpp_decltype_auto
201304 predefined __cpp_return_type_deduction
201304 predefined __has_cpp_attribute(deprecated)
201309 predefined __cpp_aggregate_nsdmi
201304 predefined __cpp_variable_templates
201304 predefined __cpp_lib_integer_sequence
201304 <utility>
__cpp_lib_exchange_function
201304 <utility>
__cpp_lib_tuples_by_type
201304 <utility>
__cpp_lib_tuple_element_t
201402 <utility>
__cpp_lib_make_unique
201304 <memory>
__cpp_lib_transparent_operators
201210 <functional>
__cpp_lib_integral_constant_callable
201304 <type_traits>
__cpp_lib_transformation_trait_aliases
201304 <type_traits>
__cpp_lib_result_of_sfinae
201210 <functional>
<type_traits>
__cpp_lib_is_final
201402 <type_traits>
__cpp_lib_is_null_pointer
201309 <type_traits>
__cpp_lib_string_udls
201304 <string>
__cpp_lib_generic_associative_lookup
201304 <map>
<set>
__cpp_lib_null_iterators
201304 <iterator>
__cpp_lib_make_reverse_iterator
201402 <iterator>
__cpp_lib_robust_nonmodifying_seq_ops
201304 <algorithm>
__cpp_lib_complex_udls
201309 <complex>
__cpp_lib_quoted_string_io
201304 <iomanip>
__has_include(<shared_mutex>)
1 predefined __cpp_lib_shared_timed_mutex
201402 <shared_mutex>
__cpp_hex_float
201603 predefined __cpp_inline_variables
201606 predefined __cpp_aligned_new
201606 predefined __cpp_guaranteed_copy_elision
201606 predefined __cpp_noexcept_function_type
201510 predefined __cpp_fold_expressions
201411 predefined __cpp_capture_star_this
201603 predefined __cpp_constexpr
201603 predefined __cpp_if_constexpr
201606 predefined __cpp_range_based_for
201603 predefined __cpp_static_assert
201411 predefined __cpp_deduction_guides
201606 predefined __cpp_deduction_guides
201611 predefined __cpp_nontype_template_parameter_auto
201606 predefined __cpp_namespace_attributes
201411 predefined __cpp_enumerator_attributes
201411 predefined __cpp_inheriting_constructors
201511 predefined __cpp_variadic_using
201611 predefined __has_cpp_attribute(fallthrough)
201603 predefined __has_cpp_attribute(nodiscard)
201603 predefined __has_cpp_attribute(maybe_unused)
201603 predefined __cpp_structured_bindings
201606 predefined __cpp_aggregate_bases
201603 predefined __cpp_nontype_template_args
201411 predefined __cpp_template_template_args
201611 predefined __cpp_fold_expressions
201603 predefined __has_include
defined predefined __cpp_lib_byte
201603 <cstddef>
__cpp_lib_hardware_interference_size
201703 <new>
__cpp_lib_launder
201606 <new>
__cpp_lib_uncaught_exceptions
201411 <exception>
__cpp_lib_as_const
201510 <utility>
__cpp_lib_make_from_tuple
201606 <tuple>
__cpp_lib_apply
201603 <tuple>
__has_include(<optional>)
1 predefined __cpp_lib_optional
201603 <optional>
__has_include(<any>)
1 predefined __cpp_lib_any
201603 <any>
__has_include(<memory_resource>)
1 predefined __cpp_lib_memory_resource
201603 <memory_resource>
__cpp_lib_boyer_moore_searcher
201603 <functional>
__has_include(<string_view>)
1 predefined __cpp_lib_string_view
201603 <string_view>
__cpp_lib_sample
201603 <algorithm>
__cpp_lib_any
201606 <any>
__cpp_lib_optional
201606 <optional>
__cpp_lib_optional
201606 <optional>
__has_include(<variant>)
1 predefined __cpp_lib_variant
201606 <variant>
__cpp_lib_addressof_constexpr
201603 <memory>
__cpp_lib_raw_memory_algorithms
201606 <memory>
__cpp_lib_transparent_operators
201510 <memory> <functional>
__cpp_lib_enable_shared_from_this
201603 <memory>
__cpp_lib_shared_ptr_weak_type
201606 <memory>
__cpp_lib_shared_ptr_arrays
201611 <memory>
__cpp_lib_invoke
201411 <functional>
__cpp_lib_not_fn
201603 <functional>
__cpp_lib_void_t
201411 <type_traits>
__cpp_lib_bool_constant
201505 <type_traits>
__cpp_lib_type_trait_variable_templates
201510 <type_traits>
__cpp_lib_logical_traits
201510 <type_traits>
__cpp_lib_is_swappable
201603 <type_traits>
__cpp_lib_is_invocable
201703 <type_traits>
__cpp_lib_has_unique_object_representations
201606 <type_traits>
__cpp_lib_is_aggregate
201703 <type_traits>
__cpp_lib_chrono
201611 <chrono>
__has_include(<execution>)
1 predefined __cpp_lib_execution
201603 <execution>
__cpp_lib_parallel_algorithm
201603 <algorithm>
<numeric>
__cpp_lib_to_chars
201611 <utility>
__cpp_lib_string_view
201606 <string> <string_view>
__cpp_lib_allocator_traits_is_always_equal
201411 <memory>
<scoped_allocator>
<string>
<deque>
<forward_list>
<list>
<vector>
<map>
<set>
<unordered_map>
<unordered_set>
__cpp_lib_incomplete_container_elements
201505 <forwardlist>
<list> <vector>__cpp_lib_map_try_emplace
201411 <map>
__cpp_lib_unordered_map_try_emplace
201411 <unordered_map>
__cpp_lib_node_extract
201606 <map> <set> <unordered_map> <unordered_set>
__cpp_lib_array_constexpr
201603 <iterator> <array>
__cpp_lib_nonmember_container_access
201411 <iterator> <array> <deque> <forward_list>
<list> <map> <regex> <set> <string>
<unordered_map> <unordered_set> <vector>__cpp_lib_clamp
201603 <algorithm>
__cpp_lib_gcd_lcm
201606 <numeric>
__cpp_lib_hypot
201603 <cmath>
__cpp_lib_math_special_functions
201603 <cmath>
__has_include(<filesystem>)
1 predefined __cpp_lib_filesystem
201703 <filesystem>
__cpp_lib_atomic_is_always_lock_free
201603 <atomic>
__cpp_lib_shared_mutex
201505 <shared_mutex>
__cpp_lib_scoped_lock
201703 <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. |