Date
2024-06-24.16:11:01
Message id
14198

Content

Proposed resolution:

This wording is relative to N4861.

  1. 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.

  2. Modify [pairs.pair] as indicated:

    -2- The defaulted move and copy constructors, respectively, of pair is a constexpr functioncan be used in a constant expression if and only if all required element-wise initializations for move and copy, respectively, would satisfy the requirements for a constexpr functioncan be used in a constant expression.

  3. Modify [tuple.cnstr] as indicated:

    -3- The defaulted move and copy constructors, respectively, of tuple is a constexpr functioncan be used in a constant expression if and only if all required element-wise initializations for move and copy, respectively, would satisfy the requirements for a constexpr functioncan be used in a constant expression. The defaulted move and copy constructors of tuple<> are constexpr functionscan be used in a constant expression.

  4. 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>
    
  5. 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.

  6. 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.

  7. 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.

  8. 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.

  9. 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:

    1. (3.1) — is_union_v<T> is false;

    2. (3.2) — is_pointer_v<T> is false;

    3. (3.3) — is_member_pointer_v<T> is false;

    4. (3.4) — is_volatile_v<T> is false; and

    5. (3.5) — T has no non-static data members of reference type.

  10. Modify [time.duration] as indicated:

    -5- The defaulted copy constructors of duration shall 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.