Proposed resolution:
This wording is relative to N4861.
Modify [constexpr.functions] as indicated:
-1- This document explicitly requires that certain standard library functions are constexpr ([dcl.constexpr]). An implementation shall not declare any standard library function signature as constexpr except for those where it is explicitly required. Within any header that provides any non-defining declarations of constexpr functions or constructors an implementation shall provide corresponding definitions.
-?- Let F denote a standard library function template or member function of a class template declared constexpr. Unless otherwise specified, a function call expression ([expr.call]) whose postfix-expression names F is a constant expression if all of the argument subexpressions are constant expressions.
Modify [pairs.pair] as indicated:
-2- The defaulted
move and copyconstructors, respectively,of pairis a constexpr functioncan be used in a constant expression if and only if all required element-wise initializationsfor move and copy, respectively, would satisfy the requirements for a constexpr functioncan be used in a constant expression.
Modify [tuple.cnstr] as indicated:
-3- The defaulted
move and copyconstructors, respectively,of tupleis a constexpr functioncan be used in a constant expression if and only if all required element-wise initializationsfor move and copy, respectively, would satisfy the requirements for a constexpr functioncan be used in a constant expression. The defaultedmove and copyconstructors of tuple<>are constexpr functionscan be used in a constant expression.
Modify [optional.ctor] as indicated:
constexpr optional() noexcept; constexpr optional(nullopt_t) noexcept;[…]-1- […]
-2- Remarks: No contained value is initialized.
For every object type T these constructors are constexpr constructors ([dcl.constexpr]).template<class... Args> constexpr explicit optional(in_place_t, Args&&... args);-12- […]
-13- […]
-14- […]
-15- […]
-16- Remarks: If T's constructor selected for the initialization is a constexpr constructor, this constructor is a constexpr constructor.template<class U, class... Args> constexpr explicit optional(in_place_t, initializer_list<U> il, Args&&... args);-17- […]
-18- […]
-19- […]
-20- […]
-21- Remarks: If T's constructor selected for the initialization is a constexpr constructor, this constructor is a constexpr constructor.template<class U = T> constexpr explicit(see below) optional(U&& v);-22- […]
-23- […]
-24- […]
-25- […]
-26- Remarks:
If T's constructor selected for the initialization is a constexpr constructor, this constructor is a constexpr constructor.The expression inside explicit is equivalent to:!is_convertible_v<U, T>
Modify [optional.observe] as indicated:
constexpr const T* operator->() const; constexpr T* operator->();-1- […]
-2- […]
-3- […]
-4- Remarks: These functions are constexpr functions.constexpr const T& operator*() const&; constexpr T& operator*() &;[…]-5- […]
-6- […]
-7- […]
-8- Remarks: These functions are constexpr functions.constexpr explicit operator bool() const noexcept;-11- Returns: true if and only if *this contains a value.
-12- Remarks: This function is a constexpr function.constexpr bool has_value() const noexcept;-13- Returns: true if and only if *this contains a value.
-14- Remarks: This function is a constexpr function.
Modify [optional.relops] as indicated:
template<class T, class U> constexpr bool operator==(const optional<T>& x, const optional<U>& y);-1- […]
-2- […]
-3- Remarks: Specializations of this function template for which *x == *y is a core constant expression are constexpr functions.template<class T, class U> constexpr bool operator!=(const optional<T>& x, const optional<U>& y);-4- […]
-5- […]
-6- Remarks: Specializations of this function template for which *x != *y is a core constant expression are constexpr functions.template<class T, class U> constexpr bool operator<(const optional<T>& x, const optional<U>& y);-7- […]
-8- […]
-9- Remarks: Specializations of this function template for which *x < *y is a core constant expression are constexpr functions.template<class T, class U> constexpr bool operator>(const optional<T>& x, const optional<U>& y);-10- […]
-11- […]
-12- Remarks: Specializations of this function template for which *x > *y is a core constant expression are constexpr functions.template<class T, class U> constexpr bool operator<=(const optional<T>& x, const optional<U>& y);-13- […]
-14- […]
-15- Remarks: Specializations of this function template for which *x <= *y is a core constant expression are constexpr functions.template<class T, class U> constexpr bool operator>=(const optional<T>& x, const optional<U>& y);-16- […]
-17- […]
-18- Remarks: Specializations of this function template for which *x >= *y is a core constant expression are constexpr functions.template<class T, three_way_comparable_with<T> U> constexpr compare_three_way_result_t<T,U> operator<=>(const optional<T>& x, const optional<U>& y);-19- Returns: If x && y, *x <=> *y; otherwise bool(x) <=> bool(y).
-20- Remarks: Specializations of this function template for which *x <=> *y is a core constant expression are constexpr functions.
Modify [variant.ctor] as indicated:
constexpr variant() noexcept(see below);[…]-1- […]
-2- […]
-3- […]
-4- […]
-5- […]
-6- Remarks:
This function is constexpr if and only if the value-initialization of the alternative type T0 would satisfy the requirements for a constexpr function.The expression inside noexcept is equivalent to is_nothrow_default_constructible_v<T0>. [Note: See also class monostate. — end note]template<class T> constexpr variant(T&& t) noexcept(see below);-14- […]
[…]
-19- Remarks: The expression inside noexcept is equivalent to is_nothrow_constructible_v<Tj, T>.
If Tj's selected constructor is a constexpr constructor, this constructor is a constexpr constructor.template<class T, class... Args> constexpr explicit variant(in_place_type_t<T>, Args&&... args);-20- […]
[…]
-24- Remarks: If T's selected constructor is a constexpr constructor, this constructor is a constexpr constructor.template<class T, class U, class... Args> constexpr explicit variant(in_place_type_t<T>, initializer_list<U> il, Args&&... args);-25- […]
[…]
-29- Remarks: If T's selected constructor is a constexpr constructor, this constructor is a constexpr constructor.template<size_t I, class... Args> constexpr explicit variant(in_place_index_t<I>, Args&&... args);-30- […]
[…]
-34- Remarks: If TI's selected constructor is a constexpr constructor, this constructor is a constexpr constructor.template<size_t I, class U, class... Args> constexpr explicit variant(in_place_index_t<I>, initializer_list<U> il, Args&&... args);-35- […]
[…]
-38- Remarks: If TI's selected constructor is a constexpr constructor, this constructor is a constexpr constructor.
Modify [move.sent.ops] as indicated:
constexpr move_sentinel();-1- Effects: Value-initializes last.
If is_trivially_default_constructible_v<S> is true, then this constructor is a constexpr constructor.
Modify [bit.cast] as indicated:
template<class To, class From> constexpr To bit_cast(const From& from) noexcept;-1- […]
-3- Remarks: This function
is constexprcan be used in a constant expression if and only if To, From, and the types of all subobjects of To and From are types T such that:
(3.1) — is_union_v<T> is false;
(3.2) — is_pointer_v<T> is false;
(3.3) — is_member_pointer_v<T> is false;
(3.4) — is_volatile_v<T> is false; and
(3.5) — T has no non-static data members of reference type.
Modify [time.duration] as indicated:
-5- The defaulted
copyconstructors of durationshall be a constexpr functioncan be used in a constant expression if and only if the required initialization of the member rep_for copy and move, respectively, would satisfy the requirements for a constexpr functioncan be used in a constant expression.