From 1102ef80f1fa0eab3d6ef40816ec35ff133ceb80 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20Kami=C5=84ski?=
--1- For value `x` of type `info`, and prvalue constant expression `X` that computes the
-reflection held by `x`, let TARG-SPLICE(x) be:
+-1- Let TARG-SPLICE(x) be:
-
--2- Returns: `true` if Z<TARG-SPLICE([:Args:])...> is a valid template-id
+-2- Returns: `true` if Z<TARG-SPLICE([:Args:])...> is a valid template-id
(
--4- [Note: If forming Z<TARG-SPLICE([:Args:])...>
+-4- [Note: If forming Z<TARG-SPLICE([:Args:])...>
leads to a failure outside of the immediate context, the program is ill-formed. — end note]
--6- Returns: Z<TARG-SPLICE([:Args:])...>.
+-6- Returns: Z<TARG-SPLICE(-7- Throws: `meta::exception` unless `can_substitute(templ, arguments)` is `true`.
--8- [Note: If forming Z<TARG-SPLICE([:Args:])...>
+-8- [Note: If forming Z<TARG-SPLICE([:Args:])...>
leads to a failure outside of the immediate context, the program is ill-formed. — end note]
This wording is relative to
Modify
Modify
template<ranges::input_range R> @@ -52,6 +51,47 @@ whereeiiti is an iterat
+This wording is relative to
Modify
+template<ranges::input_range R> + consteval info reflect_constant_array(R&& r); ++
++-8- Let T be ranges::range_value_t<R> +and ei be static_cast<T>(*iti), +where iti is an iterator to the ith element of `r`. +
+-9- Mandates: + T is a structural type (
+), + is_constructible_v<T, ranges::range_reference_t<R>> is true, and + is_copy_constructible_v<T> is true+ T satisfies copy_constructible.-10- Let V be the pack of values of type `info` of the same size as r, +where the ith element is reflect_constant(ei)
+, +where ei is an iterator to the ith element of r. +[…]
+-13- Throws: Any exception thrown by the evaluation of any ei, or +`meta::exception`
+unlessif evaluation of any reflect_constant(eei) +would exit via an exception +is a constant subexpression for every element `e` of `r`.
This wording is relative to
+Updated converting constructor and assigments to use `operator*()` +directly, required to correctly support optional<T&>. +Also update corresponding constructor in specialization. +
+ + + +
+This wording is relative to
Modify
+
+namespace std {
+ template<class T>
+ class optional {
+ public:
+ using value_type = T;
+ […]
+ private:
+ *val // exposition only;
+ union {
+ remove_cv_t<T> val; // exposition only
+ };
+ };
+
+ […]
+}
+
+
+Modify
+++-1- + +When its member val is active +(
+), +an instance of optional<T>is said to +contain a value, and val is referred to as its +contained value. + ++An object of type+An +optional object's +contained value +optional<T>at any given time either +contains a value or does not contain a value. +When an object of typeoptional<T>contains a value, +it means that an object of typeT, +referred to as thecontained value,+is nested within () the optional object. + +When an object of type+optional<T>+is contextually converted tobool, +the conversion returns `true` if the object contains a value; +otherwise the conversion returns `false`. ++
++-2- When an optional<T> object contains a value, +member val +points to the contained value. ++
Modify
+++constexpr optional(const optional& rhs); +++++-4- Effects: If rhs contains a value, direct-non-list-initializes +val
+-5- Postconditions: rhs.has_value() == this->has_value(). + +[…] + +the contained valuewith*rhs.val. ++constexpr optional(optional&& rhs) noexcept(see below); +++++-8- Constraints: […] +
+-9- Effects: If rhs contains a value, direct-non-list-initializes +valthe contained valuewith std::move(*rhs.val). +rhs.has_value() is unchanged. + +-10- Postconditions: rhs.has_value() == this->has_value(). + +[…] + ++template<class... Args> constexpr explicit optional(in_place_t, Args&&... args); +++++-13- Constraints: […] +
+-14- Effects: Direct-non-list-initializes valthe contained value+with std::forward<Args>(args).... + +-15- Postconditions: *this contains a value. + +[…] + ++template<class U, class... Args> + constexpr explicit optional(in_place_t, initializer_list<U> il, Args&&... args); +++++-18- Constraints: […] +
+-19- Effects: Direct-non-list-initializes valthe contained value+with il, std::forward<Args>(args).... + +-20- Postconditions: *this contains a value. + +[…] + ++template<class U = T> constexpr explicit(see below) optional(U&& v); +++++-23- Constraints: […] +
+-24- Effects: Direct-non-list-initializes valthe contained value+with std::forward<U>(v). + +-25- Postconditions: *this contains a value. + +[…] + ++template<class U> constexpr explicit(see below) optional(const optional<U>& rhs); +++++-28- Constraints: […] +
+-29- Effects: If rhs contains a value, direct-non-list-initializes +valthe contained valuewith*rhs.operator*(). + +-30- Postconditions: rhs.has_value() == this->has_value(). + +[…] + ++template<class U> constexpr explicit(see below) optional(optional<U>&& rhs); +++++-33- Constraints: […] +
+-34- Effects: If rhs contains a value, direct-non-list-initializes +valthe contained valuewith +*std::move(rhs).operator*(). rhs.has_value() is unchanged. + +-35- Postconditions: rhs.has_value() == this->has_value(). + +[…] + +
Modify
+++constexpr ~optional(); +++++-1- Effects: If is_trivially_destructible_v<T> != true and *this contains a value, +calls
+val->val.T::~T(). +
Modify
+++constexpr optional<T>& operator=(nullopt_t) noexcept; +++++-1- Effects: If *this contains a value, calls +
+-2- Postconditions: *this does not contain a value. + +val->val.T::~T() to destroy the contained +value; otherwise no effect. ++constexpr optional<T>& operator=(const optional& rhs); +++++-4- Effects: See Table 58. +
++
+Table 58 — optional::operator=(const optional&) effects [tab:optional.assign.copy] + ++ + ++ *this contains a value +*this does not contain a value ++ + +rhs contains a value +assigns +*rhs.val to valthe contained valuedirect-non-list-initializes val +the contained value+with*rhs.val
++ +rhs does not contain a value +destroys the contained value by calling +val->val.T::~T()
+no effect ++-5- Postconditions: rhs.has_value() == this->has_value(). +
+[…] + ++constexpr optional<T>& operator=(optional&& rhs) noexcept(see below); +++++-8- Constraints: […] +
+-9- Effects: See Table 59. The result of the expression rhs.has_value() remains unchanged. + +-10- Postconditions: rhs.has_value() == this->has_value(). + +-11- Returns: *this. + ++
+Table 59 — optional::operator=(optional&&) effects [tab:optional.assign.move] + ++ + ++ *this contains a value +*this does not contain a value ++ + +rhs contains a value +assigns std::move( +*rhs.val) to valthe contained valuedirect-non-list-initializes val +the contained valuewith +std::move(*rhs.val)+ +rhs does not contain a value +destroys the contained value by calling +
+val->val.T::~T()no effect ++-12- Remarks: […] +
+-13- If any exception is thrown, the result of the expression this->has_value() remains +unchanged. If an exception is thrown during the call to T's move constructor, the state +of*rhs.valvalis determined by the exception +safety guarantee of T's move constructor. If an exception is thrown during the call to +T's move assignment, the statesstateof*valval+and*rhs.valvalareisdetermined by the exception +safety guarantee of T's move assignment. + ++template<class U = T> constexpr optional<T>& operator=(U&& v); +++++-14- Constraints: […] +
+-15- Effects: If *this contains a value, assigns std::forward<U>(v) +to valthe contained value; otherwise direct-non-list-initializes +valthe contained valuewith std::forward<U>(v). + +-16- Postconditions: *this contains a value. + +-17- Returns: *this. + +-18- Remarks: If any exception is thrown, the result of the expression this->has_value() +remains unchanged. If an exception is thrown during the call to T's constructor, the state of +v is determined by the exception safety guarantee of T's constructor. If an exception +is thrown during the call to T's assignment, the statesstateof val*val+and v areisdetermined by the exception safety guarantee of T's assignment. + ++template<class U> constexpr optional<T>& operator=(const optional<U>& rhs); +++++-19- Constraints: […] +
+-20- Effects: See Table 60. + ++
+Table 60 — optional::operator=(const optional<U>&) effects [tab:optional.assign.copy.templ] + ++ + ++ *this contains a value +*this does not contain a value ++ + +rhs contains a value +assigns +*rhs.operator*() to valthe contained valuedirect-non-list-initializes val +the contained value+with*rhs.operator*()+ +rhs does not contain a value +destroys the contained value by calling +
+val->val.T::~T()no effect ++-21- Postconditions: rhs.has_value() == this->has_value(). +
+-22- Returns: *this. + +-23- If any exception is thrown, the result of the expression this->has_value() remains +unchanged. If an exception is thrown during the call to T's constructor, the state of +*rhs.valvalis determined by the exception safety +guarantee of T's constructor. If an exception is thrown during the call to T's +assignment, the statesstateof val*valand +*rhs.valvalareisdetermined by the exception safety +guarantee of T's assignment. + ++template<class U> constexpr optional<T>& operator=(optional<U>&& rhs); +++++-24- Constraints: […] +
+-25- Effects: See Table 61. The result of the expression rhs.has_value() remains unchanged. + ++
+Table 61 — optional::operator=(optional<U>&&) effects [tab:optional.assign.move.templ] + ++ + ++ *this contains a value +*this does not contain a value ++ + +rhs contains a value +assigns +*std::move(rhs).operator*() to valthe contained valuedirect-non-list-initializes val +the contained valuewith
+*std::move(rhs).operator*()+ +rhs does not contain a value +destroys the contained value by calling +
+val->val.T::~T()no effect ++-26- Postconditions: rhs.has_value() == this->has_value(). +
+-27- Returns: *this. + +-28- If any exception is thrown, the result of the expression this->has_value() remains +unchanged. If an exception is thrown during the call to T's constructor, the state of +*rhs.valvalis determined by the exception safety +guarantee of T's constructor. If an exception is thrown during the call to T's +assignment, the statesstateof val*valand +*rhs.valvalareisdetermined by the exception safety +guarantee of T's assignment. + ++template<class... Args> constexpr T& emplace(Args&&... args); +++++-29- Mandates: […] +
+-30- Effects: Calls *this = nullopt. Then direct-non-list-initializes +valthe contained valuewith std::forward<Args>(args).... + +-31- Postconditions: *this contains a value. + +-32- Returns: valA reference to the new contained value. + +[…] + +-34- Remarks: If an exception is thrown during the call to T's constructor, *this +does not contain a value, and the previous val*val(if any) +has been destroyed. + ++template<class U, class... Args> constexpr T& emplace(initializer_list<U> il, Args&&... args); +++++-35- Constraints: […] +
+-36- Effects: Calls *this = nullopt. Then direct-non-list-initializes +valthe contained valuewith il, std::forward<Args>(args).... + +-37- Postconditions: *this contains a value. + +-38- Returns: valA reference to the new contained value. + +[…] + +-40- Remarks: If an exception is thrown during the call to T's constructor, *this +does not contain a value, and the previous val*val(if any) +has been destroyed. + +
Modify
+++constexpr void swap(optional& rhs) noexcept(see below); +++++-1- Mandates: […] +
+-2- Preconditions: […] + +-3- Effects: See Table 62. + ++
+Table 62 — optional::swap(optional&) effects [tab:optional.swap] + ++ + ++ *this contains a value +*this does not contain a value ++ + +rhs contains a value +calls swap(val +*(*this),*rhs.val)direct-non-list-initializes val +the contained value of *this
+with std::move(*rhs.val), followed by rhs.val.val->T::~T();
+postcondition is that *this contains a value and rhs does
+not contain a value+ +rhs does not contain a value +direct-non-list-initializes +the contained value ofrhs.val
+with std::move(val*(*this)), followed by val.val->T::~T();
+postcondition is that *this does not contain a value and rhs
+contains a valueno effect ++-4- Throws: […] +
+-5- Remarks: […] + +-6- If any exception is thrown, the results of the expressions this->has_value() and +rhs.has_value() remain unchanged. If an exception is thrown during the call to function swap, +the state of val*valand +*rhs.valvalis determined by the exception safety +guarantee of swap for lvalues of T. If an exception is thrown during the call to +T's move constructor, the statesstateof val*valand +*rhs.valvalareisdetermined by the exception safety +guarantee of T's move constructor. + + +
Modify
+++constexpr const T* operator->() const noexcept; +constexpr T* operator->() noexcept; +++++-1- Preconditions: *this contains a value. +
+-2- Returns: addressof(val)val. + +-3- […] + ++constexpr const T& operator*() const & noexcept; +constexpr T& operator*() & noexcept; +++++-4- Preconditions: *this contains a value. +
+-5- Returns: val*val. + +-6- […] + ++constexpr T&& operator*() && noexcept; +constexpr const T&& operator*() const && noexcept; +++++-7- Preconditions: *this contains a value. +
+-8- Effects: Equivalent to: return std::move(val*val); + ++constexpr explicit operator bool() const noexcept; +++++-9- Returns: true if and only if *this contains a value. +
+-10- Remarks: This function is a constexpr function. + ++constexpr bool has_value() const noexcept; +++++-11- Returns: true if and only if *this contains a value. +
+-12- Remarks: This function is a constexpr function. + ++constexpr const T& value() const &; +constexpr T& value() &; +++++-13- Effects: Equivalent to: +
+++return has_value() ? val*val: throw bad_optional_access(); ++constexpr T&& value() &&; +constexpr const T&& value() const &&; +++++-14- Effects: Equivalent to: +
+++return has_value() ? std::move(val*val) : throw bad_optional_access(); ++template<class U> constexpr T value_or(U&& v) const &; +++++-15- Mandates: […] +
+-16- Effects: Equivalent to: + +++return has_value() ? val**this: static_cast<T>(std::forward<U>(v)); ++template<class U> constexpr T value_or(U&& v) &&; +++++-17- Mandates: […] +
+-18- Effects: Equivalent to: + +++return has_value() ? std::move(val**this) : static_cast<T>(std::forward<U>(v)); +
Modify
+++template<class F> constexpr auto and_then(F&& f) &; +template<class F> constexpr auto and_then(F&& f) const &; +++++-1- Let U be invoke_result_t<F, decltype((val)
+-2- Mandates: […] + +-3- Effects: Equivalent to: + +*val)>. +++if (*this) { + return invoke(std::forward<F>(f), val*val); +} else { + return remove_cvref_t<U>(); +} ++template<class F> constexpr auto and_then(F&& f) &&; +template<class F> constexpr auto and_then(F&& f) const &&; +++++-4- Let U be invoke_result_t<F, decltype(std::move(val
+-5- Mandates: […] + +-6- Effects: Equivalent to: + +*val))>. +++if (*this) { + return invoke(std::forward<F>(f), std::move(val*val)); +} else { + return remove_cvref_t<U>(); +} ++template<class F> constexpr auto transform(F&& f) &; +template<class F> constexpr auto transform(F&& f) const &; +++++-7- Let U be remove_cv_t<invoke_result_t<F, decltype((val)
+-8- Mandates: U is a non-array object type other than in_place_t or nullopt_t. The declaration + +*val)>>. +++U u(invoke(std::forward<F>(f), val*val)); ++is well-formed for some invented variable u. +
+[…] + +-9- Returns: If *this contains a value, an optional<U> object whose contained value is +direct-non-list-initialized with invoke(std::forward<F>(f), val*val); otherwise, +optional<U>(). + ++template<class F> constexpr auto transform(F&& f) &&; +template<class F> constexpr auto transform(F&& f) const &&; +++++-10- Let U be remove_cv_t<invoke_result_t<F, decltype(std::move(val
+-11- Mandates: U is a non-array object type other than in_place_t or nullopt_t. The declaration + +*val))>>. +++U u(invoke(std::forward<F>(f), std::move(val*val))); ++is well-formed for some invented variable u. +
+[…] + +-12- Returns: If *this contains a value, an optional<U> object whose contained value is +direct-non-list-initialized with invoke(std::forward<F>(f), std::move(val*val)); otherwise, +optional<U>(). + +
Modify
+++constexpr void reset() noexcept; +++++-1- Effects: If *this contains a value, calls
+-2- Postconditions: *this does not contain a value. + +val->val.T::~T() +to destroy the contained value; otherwise no effect. +
Modify
+template<class U> + constexpr explicit(!is_convertible_v<U&, T&>) + optional(optional<U>& rhs) noexcept(is_nothrow_constructible_v<T&, U&>); ++
+ +-8- Constraints: […] + +-9- Effects: Equivalent to: ++ ++ if (rhs.has_value()) convert-ref-init-val(+ +-10- Remarks: […] +*rhs.operator*()); +
+template<class U> + constexpr explicit(!is_convertible_v<const U&, T&>) + optional(const optional<U>& rhs) noexcept(is_nothrow_constructible_v<T&, const U&>); ++
+ +-11- Constraints: […] + +-12- Effects: Equivalent to: ++ ++ if (rhs.has_value()) convert-ref-init-val(+ +-13- Remarks: […] +*rhs.operator*()); +
+template<class U> + constexpr explicit(!is_convertible_v<U, T&>) + optional(optional<U>&& rhs) noexcept(is_nothrow_constructible_v<T&, U>); ++
+ +-14- Constraints: […] + +-15- Effects: Equivalent to: ++ ++ if (rhs.has_value()) convert-ref-init-val(+ +-16- Remarks: […] +*std::move(rhs).operator*()); +
+template<class U> + constexpr explicit(!is_convertible_v<const U, T&>) + optional(const optional<U>&& rhs) noexcept(is_nothrow_constructible_v<T&, const U>); ++
+ +-17- Constraints: […] + +-18- Effects: Equivalent to: +++ if (rhs.has_value()) convert-ref-init-val(+ +-19- Remarks: […] +*std::move(rhs).operator*()); +