23 Iterators library [iterators]

23.3 Iterator requirements [iterator.requirements]

23.3.3 Customization points [iterator.cust] ranges​::​iter_­swap [iterator.cust.swap]

The name ranges​::​iter_­swap denotes a customization point object ([customization.point.object]) that exchanges the values ([concept.swappable]) denoted by its arguments.
Let iter-exchange-move be the exposition-only function:
template<class X, class Y> constexpr iter_value_t<remove_reference_t<X>> iter-exchange-move(X&& x, Y&& y) noexcept(noexcept(iter_value_t<remove_reference_t<X>>(iter_move(x))) && noexcept(*x = iter_move(y)));
Effects: Equivalent to:
iter_value_t<remove_reference_t<X>> old_value(iter_move(x));
*x = iter_move(y);
return old_value;
The expression ranges​::​iter_­swap(E1, E2) for some subexpressions E1 and E2 is expression-equivalent to:
  • (void)iter_­swap(E1, E2), if that expression is valid, with overload resolution performed in a context that includes the declaration
    template<class I1, class I2>
      void iter_swap(I1, I2) = delete;
    and does not include a declaration of ranges​::​iter_­swap. If the function selected by overload resolution does not exchange the values denoted by E1 and E2, the program is ill-formed with no diagnostic required.
  • Otherwise, if the types of E1 and E2 each model readable, and if the reference types of E1 and E2 model swappable_­with ([concept.swappable]), then ranges​::​swap(*E1, *E2).
  • Otherwise, if the types T1 and T2 of E1 and E2 model indirectly_­movable_­storable<T1, T2> and indirectly_­movable_­storable<T2, T1>, then (void)(*E1 = iter-exchange-move(E2, E1)), except that E1 is evaluated only once.
  • Otherwise, ranges​::​iter_­swap(E1, E2) is ill-formed.
    : This case can result in substitution failure when ranges​::​iter_­swap(E1, E2) appears in the immediate context of a template instantiation. — end note