7 Concepts library [concepts.lib]

7.3 Core language concepts [concepts.lib.corelang]

7.3.11 Concept Swappable [concepts.lib.corelang.swappable]

template <class T> concept bool Swappable = requires(T& a, T& b) { ranges::swap(a, b); }; template <class T, class U> concept bool SwappableWith = CommonReference< const remove_reference_t<T>&, const remove_reference_t<U>&> && requires(T&& t, U&& u) { ranges::swap(std::forward<T>(t), std::forward<T>(t)); ranges::swap(std::forward<U>(u), std::forward<U>(u)); ranges::swap(std::forward<T>(t), std::forward<U>(u)); ranges::swap(std::forward<U>(u), std::forward<T>(t)); };

This subclause provides definitions for swappable types and expressions. In these definitions, let t denote an expression of type T, and let u denote an expression of type U.

An object t is swappable with an object u if and only if SwappableWith<T, U> is satisfied. SwappableWith<T, U> is satisfied only if given distinct objects t2 equal to t and u2 equal to u, after evaluating either ranges::swap(t, u) or ranges::swap(u, t), t2 is equal to u and u2 is equal to t.

An rvalue or lvalue t is swappable if and only if t is swappable with any rvalue or lvalue, respectively, of type T.

Example: User code can ensure that the evaluation of swap calls is performed in an appropriate context under the various conditions as follows:

#include <utility>

// Requires: std::forward<T>(t) shall be swappable with std::forward<U>(u).
template <class T, class U>
void value_swap(T&& t, U&& u) {
  using std::experimental::ranges::swap;
  swap(std::forward<T>(t), std::forward<U>(u));         // OK: uses “swappable with” conditions
                                                        // for rvalues and lvalues
}

// Requires: lvalues of T shall be swappable.
template <class T>
void lv_swap(T& t1, T& t2) {
  using std::experimental::ranges::swap;
  swap(t1, t2);                                         // OK: uses swappable conditions for
}                                                       // lvalues of type T

namespace N {
  struct A { int m; };
  struct Proxy { A* a; };
  Proxy proxy(A& a) { return Proxy{ &a }; }

  void swap(A& x, Proxy p) {
    std::experimental::ranges::swap(x.m, p.a->m);  // OK: uses context equivalent to swappable
                                                   // conditions for fundamental types
  }
  void swap(Proxy p, A& x) { swap(x, p); }         // satisfy symmetry constraint
}

int main() {
  int i = 1, j = 2;
  lv_swap(i, j);
  assert(i == 2 && j == 1);

  N::A a1 = { 5 }, a2 = { -5 };
  value_swap(a1, proxy(a2));
  assert(a1.m == -5 && a2.m == 5);
}

 — end example ]