3413. [fund.ts.v3] propagate_const's swap's noexcept specification needs to be constrained and use a trait

Section: 3.2.2.7 [fund.ts.v3::propagate_const.modifiers], 3.2.2.9 [fund.ts.v3::propagate_const.algorithms] Status: C++23 Submitter: Thomas Köppe Opened: 2020-02-29 Last modified: 2023-11-22

Priority: 0

View all issues with C++23 status.

Discussion:

Addresses: fund.ts.v3

In the Fundamentals TS, the noexcept specifications of both the member and non-member swap functions for propagate_const are using the old, ill-formed pattern of attempting to use "noexcept(swap(...))" as the boolean predicate. According to LWG 2456, this is ill-formed, and a resolution such as in P0185R1 is required.

Previous resolution [SUPERSEDED]:

This wording is relative to N4840.

  1. Modify 3.2.1 [fund.ts.v3::propagate_const.syn], header <experimental/propagate_const> synopsis, as indicated:

    // 3.2.2.9 [fund.ts.v3::propagate_const.algorithms], propagate_const specialized algorithms
    template <class T>
      constexpr void swap(propagate_const<T>& pt, propagate_const<T>& pt2) noexcept(see belowis_nothrow_swappable_v<T>);
    
  2. Modify 3.2.2.1 [fund.ts.v3::propagate_const.overview], class template propagate_const synopsis, as indicated:

    // 3.2.2.7 [fund.ts.v3::propagate_const.modifiers], propagate_const modifiers
    constexpr void swap(propagate_const& pt) noexcept(see belowis_nothrow_swappable_v<T>);
    
  3. Modify 3.2.2.7 [fund.ts.v3::propagate_const.modifiers] as indicated:

    constexpr void swap(propagate_const& pt) noexcept(see belowis_nothrow_swappable_v<T>);
    

    -2- The constant-expression in the exception-specification is noexcept(swap(t_, pt.t_)).

    -3- Effects: swap(t_, pt.t_).

  4. Modify 3.2.2.9 [fund.ts.v3::propagate_const.algorithms] as indicated:

    template <class T>
      constexpr void swap(propagate_const<T>& pt1, propagate_const<T>& pt2) noexcept(see belowis_nothrow_swappable_v<T>);
    

    -2- The constant-expression in the exception-specification is noexcept(pt1.swap(pt2)).

    -3- Effects: pt1.swap(pt2).

[2020-03-30; Reflector discussion]

This issue has very much overlap with LWG 2561, especially now that the library fundamentals has been rebased to C++20 the there reported problem for the corresponding swap problem for optional is now moot. During the reflector discussion of this issue here it was also observed that the free swap template for propagate_const needs to be constrained. This has been done below in the revised wording which also attempts to use a similar style as the IS.

Previous resolution [SUPERSEDED]:

This wording is relative to N4840.

  1. Modify 3.2.2.1 [fund.ts.v3::propagate_const.overview], class template propagate_const synopsis, as indicated:

    // 3.2.2.7 [fund.ts.v3::propagate_const.modifiers], propagate_const modifiers
    constexpr void swap(propagate_const& pt) noexcept(see belowis_nothrow_swappable_v<T>);
    
  2. Modify 3.2.2.7 [fund.ts.v3::propagate_const.modifiers] as indicated:

    constexpr void swap(propagate_const& pt) noexcept(see belowis_nothrow_swappable_v<T>);
    

    -2- The constant-expression in the exception-specification is noexcept(swap(t_, pt.t_)).

    -3- Effects: swap(t_, pt.t_).

  3. Modify 3.2.2.9 [fund.ts.v3::propagate_const.algorithms] as indicated:

    template <class T>
      constexpr void swap(propagate_const<T>& pt1, propagate_const<T>& pt2) noexcept(see below);
    

    -?- Constraints: is_swappable_v<T> is true.

    -2- The constant-expression in the exception-specification is noexcept(pt1.swap(pt2)).

    -3- Effects: pt1.swap(pt2).

    -?- Remarks: The expression inside noexcept is equivalent to:

    noexcept(pt1.swap(pt2))
    

[2020-04-06; Wording update upon reflector discussions]

[2020-05-03 Issue Prioritization]

Status set to Tentatively Ready after five positive votes on the reflector.

[2020-11-09 Approved In November virtual meeting. Status changed: Tentatively Ready → WP.]

Proposed resolution:

This wording is relative to N4840.

  1. Modify 3.2.2.1 [fund.ts.v3::propagate_const.overview], class template propagate_const synopsis, as indicated:

    // 3.2.2.7 [fund.ts.v3::propagate_const.modifiers], propagate_const modifiers
    constexpr void swap(propagate_const& pt) noexcept(see belowis_nothrow_swappable_v<T>);
    
  2. Modify 3.2.2.7 [fund.ts.v3::propagate_const.modifiers] as indicated:

    constexpr void swap(propagate_const& pt) noexcept(see belowis_nothrow_swappable_v<T>);
    

    -?- Preconditions: Lvalues of type T are swappable (C++17 §20.5.3.2).

    -2- The constant-expression in the exception-specification is noexcept(swap(t_, pt.t_)).

    -3- Effects: swap(t_, pt.t_).

  3. Modify 3.2.2.9 [fund.ts.v3::propagate_const.algorithms] as indicated:

    template <class T>
      constexpr void swap(propagate_const<T>& pt1, propagate_const<T>& pt2) noexcept(see below);
    

    -?- Constraints: is_swappable_v<T> is true.

    -2- The constant-expression in the exception-specification is noexcept(pt1.swap(pt2)).

    -3- Effects: Equivalent to: pt1.swap(pt2).

    -?- Remarks: The expression inside noexcept is equivalent to:

    noexcept(pt1.swap(pt2))