4056. The effects of std::swap are under-specified

Section: 22.2.2 [utility.swap] Status: NAD Submitter: Jan Schultke Opened: 2024-02-28 Last modified: 2024-06-24

Priority: Not Prioritized

View all other issues in [utility.swap].

View all issues with NAD status.

Discussion:

Subclause 22.2.2 [utility.swap] describes the effect of std::swap as follows:

Effects: Exchanges values stored in two locations.

This description is extremely vague. A possible implementation which complies with this wording is:

template<class T>
constexpr void swap(T&, T&) noexcept(/* ... */)
{
    int __x = 0, __y = 0;
    int __z = __x;
    __x = __y;
    __y = __z;
}

This exchanges values stored in two locations; namely in the locations of two objects with automatic storage duration within swap. Since this has no observable effect and complies, it is also valid to implement swap as follows:

template<class T>
constexpr void swap(T&, T&) noexcept(/* ... */) { }

Furthermore, there is implementation divergence. libc++ uses direct-initialization to construct a temporary T, but libstdc++ uses copy-initialization. For most types, this hopefully calls the same constructor, however, this is not universally true. The standard should specify in more detail what is meant to happen.

[2024-03-15; Reflector poll]

Set status to Tentatively NAD Editorial after reflector poll.

Cpp17MoveConstructible require direct-init and copy-init to be semantically equivalent, so the different implementation techniques can only be observed by types which fail to meet the function's preconditions.

Replace the unusual "stored in two locations" wording editorially.

[St. Louis 2024-06-24 Status changed: Tentatively NAD → NAD.]

Proposed resolution:

This wording is relative to N4971.

  1. Modify 22.2.2 [utility.swap] as indicated:

    template<class T>
      constexpr void swap(T& a, T& b) noexcept(see below);
    

    -1- Constraints: is_move_constructible_v<T> is true and is_move_assignable_v<T> is true.

    -2-Preconditions: Type T meets the Cpp17MoveConstructible (Table 31) and Cpp17MoveAssignable (Table 33) requirements.

    -3- Effects: Exchanges values stored in two locations.Equivalent to:

    auto t(std::move(a));
    a = std::move(b);
    b = std::move(t);
    

    -4- Remarks: The exception specification is equivalent to: […]