Created on 2017-02-03.00:00:00 last changed 45 months ago
Proposed resolution:
This wording is relative to N4800.
Modify [tuple.cnstr] as indicated:
tuple(tuple&& u) = default;-13-
-14- Effects: For all i, initializes the ith element of *this with std::forward<Ti>(get<i>(u)).RequiresConstraints: is_move_constructible_v<Ti> is true for all i.
Modify [unique.ptr.single.ctor] as indicated:
unique_ptr(unique_ptr&& u) noexcept;-?- Constraints: is_move_constructible_v<D> is true.
-15- Requires: If D is not a reference type, D shall satisfy the Cpp17MoveConstructible requirements (Table 26). Construction of the deleter from an rvalue of type D shall not throw an exception. […]
Modify [unique.ptr.single.asgn] as indicated:
unique_ptr& operator=(unique_ptr&& u) noexcept;-?- Constraints: is_move_assignable_v<D> is true.
-1- Requires: If D is not a reference type, D shall satisfy the Cpp17MoveAssignable requirements (Table 28) and assignment of the deleter from an rvalue of type D shall not throw an exception. Otherwise, D is a reference type; remove_reference_t<D> shall satisfy the Cpp17CopyAssignable requirements and assignment of the deleter from an lvalue of type D shall not throw an exception. -2- Effects: Calls reset(u.release()) followed by get_deleter() = std::forward<D>(u.get_deleter()). […]
[ 2019-02; Kona Wednesday night issue processing ]
Status to Ready
[ 2019-02-14; Jonathan comments and provides revised wording ]
The suggested change was already made to std::optional by LWG 2756. The current P/R for 2899 doesn't resolve the issue for std::tuple or std::unique_ptr. I hope the following alternative does.
[ 2016-07, Toronto Thursday night issues processing ]
The description doesn't match the resolution; Alisdair to investigate. Status to Open
Previous resolution [SUPERSEDED]:
This wording is relative to N4640.
Modify [tuple.tuple] as indicated:
// 20.5.3.1, tuple construction EXPLICIT constexpr tuple(); EXPLICIT constexpr tuple(const Types&...); // only if sizeof...(Types) >= 1 template <class... UTypes> EXPLICIT constexpr tuple(UTypes&&...) noexcept(see below); // only if sizeof...(Types) >= 1 tuple(const tuple&) = default; tuple(tuple&&) = default; template <class... UTypes> EXPLICIT constexpr tuple(const tuple<UTypes...>&); template <class... UTypes> EXPLICIT constexpr tuple(tuple<UTypes...>&&) noexcept(see below); template <class U1, class U2> EXPLICIT constexpr tuple(const pair<U1, U2>&); // only if sizeof...(Types) == 2 template <class U1, class U2> EXPLICIT constexpr tuple(pair<U1, U2>&&) noexcept(see below); // only if sizeof...(Types) == 2 […] // 20.5.3.2, tuple assignment tuple& operator=(const tuple&); tuple& operator=(tuple&&) noexcept(see below); template <class... UTypes> tuple& operator=(const tuple<UTypes...>&); template <class... UTypes> tuple& operator=(tuple<UTypes...>&&) noexcept(see below); template <class U1, class U2> tuple& operator=(const pair<U1, U2>&); // only if sizeof...(Types) == 2 template <class U1, class U2> tuple& operator=(pair<U1, U2>&&) noexcept(see below); // only if sizeof...(Types) == 2Modify [tuple.cnstr] as indicated:
template <class... UTypes> EXPLICIT constexpr tuple(UTypes&&... u) noexcept(see below);-8- Effects: Initializes the elements in the tuple with the corresponding value in std::forward<UTypes>(u).
-9- Remarks: This constructor shall not participate in overload resolution unless sizeof...(Types) == sizeof...(UTypes) and sizeof...(Types) >= 1 and is_constructible_v<Ti, Ui&&> is true for all i. The constructor is explicit if and only if is_convertible_v<Ui&&, Ti> is false for at least one i. The expression inside noexcept is equivalent to the logical AND of the following expressions:is_nothrow_constructible_v<Ti, Ui&&>where Ti is the ith type in Types, and Ui is the ith type in UTypes.
[…]
template <class... UTypes> EXPLICIT constexpr tuple(tuple<UTypes...>&& u) noexcept(see below);-16- Effects: For all i, initializes the ith element of *this with std::forward<Ui>(get<i>(u)).
-17- Remarks: This constructor shall not participate in overload resolution unless […] The constructor is explicit if and only if is_convertible_v<Ui&&, Ti> is false for at least one i. The expression inside noexcept is equivalent to the logical AND of the following expressions:is_nothrow_constructible_v<Ti, Ui&&>where Ti is the ith type in Types, and Ui is the ith type in UTypes.
[…]
template <class U1, class U2> EXPLICIT constexpr tuple(pair<U1, U2>&& u) noexcept(see below);-21- Effects: Initializes the first element with std::forward<U1>(u.first) and the second element with std::forward<U2>(u.second).
-22- Remarks: This constructor shall not participate in overload resolution unless sizeof...(Types) == 2, is_constructible_v<T0, U1&&> is true and is_constructible_v<T1, U2&&> is true. -23- The constructor is explicit if and only if is_convertible_v<U1&&, T0> is false or is_convertible_v<U2&&, T1> is false. The expression inside noexcept is equivalent to:is_nothrow_constructible_v<T0, U1&&> && is_nothrow_constructible_v<T1, U2&&>Modify [tuple.assign] as indicated:
template <class... UTypes> tuple& operator=(tuple<UTypes...>&& u) noexcept(see below);-12- Effects: For all i, assigns std::forward<Ui>(get<i>(u)) to get<i>(*this).
-13- Remarks: This operator shall not participate in overload resolution unless is_assignable_v<Ti&, Ui&&> == true for all i and sizeof...(Types) == sizeof...(UTypes). The expression inside noexcept is equivalent to the logical AND of the following expressions:is_nothrow_assignable_v<Ti&, Ui&&>where Ti is the ith type in Types, and Ui is the ith type in UTypes.
-14- Returns: *this.
[…]
template <class U1, class U2> tuple& operator=(pair<U1, U2>&& u) noexcept(see below);-18- Effects: Assigns std::forward<U1>(u.first) to the first element of *this and std::forward<U2>(u.second) to the second element of *this.
-19- Remarks: This operator shall not participate in overload resolution unless sizeof...(Types) == 2 and is_assignable_v<T0&, U1&&> is true for the first type T0 in Types and is_assignable_v<T1&, U2&&> is true for the second type T1 in Types. The expression inside noexcept is equivalent to:is_nothrow_assignable_v<T0&, U1&&> && is_nothrow_assignable_v<T1&, U2&&>-20- Returns: *this.
[ 2017-06-27 P2 after 5 positive votes on c++std-lib. ]
[ 2017-02-26, Scott Schurr provides wording ]
The move constructors for tuple, optional, and unique_ptr should return false for is_(nothrow_)move_constructible_v<TYPE> when their corresponding Requires clauses are not satisfied, as there are now several library clauses that are defined in terms of these traits. The same concern applies to the move-assignment operator. Note that pair and variant already satisfy this constraint.
History | |||
---|---|---|---|
Date | User | Action | Args |
2021-02-25 10:48:01 | admin | set | status: wp -> c++20 |
2019-07-22 15:46:37 | admin | set | status: voting -> wp |
2019-06-17 05:25:36 | admin | set | status: ready -> voting |
2019-02-21 17:23:36 | admin | set | messages: + msg10313 |
2019-02-21 17:23:36 | admin | set | status: open -> ready |
2019-02-14 19:58:58 | admin | set | messages: + msg10309 |
2017-07-16 20:11:05 | admin | set | messages: + msg9416 |
2017-07-16 20:11:05 | admin | set | status: new -> open |
2017-06-27 21:48:39 | admin | set | messages: + msg9306 |
2017-02-27 22:06:49 | admin | set | messages: + msg9008 |
2017-02-27 22:06:49 | admin | set | messages: + msg9007 |
2017-02-03 00:00:00 | admin | create |