The name swap denotes a customization point object ([customization.point.object]). The effect of the expression ranges::swap(E1, E2) for some expressions E1 and E2 is equivalent to:

(void)swap(E1, E2), if that expression is valid, with overload resolution performed in a context that includes the declarations

template <class T> void swap(T&, T&) = delete; template <class T, size_t N> void swap(T(&)[N], T(&)[N]) = delete;

and does not include a declaration of ranges::swap. If the function selected by overload resolution does not exchange the values referenced by E1 and E2, the program is ill-formed with no diagnostic required.

Otherwise, (void)swap_ranges(E1, E2) if E1 and E2 are lvalues of array types ( ISO/IEC 14882:2014 §[basic.compound]) of equal extent and ranges::swap(*(E1), *(E2)) is a valid expression, except that noexcept(ranges::swap(E1, E2)) is equal to noexcept(ranges::swap(*(E1), *(E2))).

Otherwise, if E1 and E2 are lvalues of the same type T which meets the syntactic requirements of MoveConstructible<T> and Assignable<T&, T>, exchanges the referenced values. ranges::swap(E1, E2) is a constant expression if the constructor selected by overload resolution for T{std::move(E1)} is a constexpr constructor and the expression E1 = std::move(E2) can appear in a constexpr function. noexcept(ranges::swap(E1, E2)) is equal to is_nothrow_move_constructible<T>::value && is_nothrow_move_assignable<T>::value. If either MoveConstructible or Assignable is not satisfied, the program is ill-formed with no diagnostic required.

Otherwise, ranges::swap(E1, E2) is ill-formed.

*Remark:* Whenever ranges::swap(E1, E2) is a valid
expression, it exchanges the values referenced by E1
and E2 and has type void.