0

What is the standard way of calling swap() for arguments defined by template?

Obviously calling std::swap() is not correct, as it would not pick up the swap declared in the same namespace as the type. It seems that inserting a using namespace std; is not correct as it leads to errors. Should one insert a using std::swap;?

Frank Puck
  • 467
  • 1
  • 11
  • 1
    You should add an example code to your question. – Jason Nov 15 '22 at 15:50
  • The cited answer does not apply to my question! I did not ask how to implement a swap but how to call it. – Frank Puck Nov 15 '22 at 16:09
  • 1
    @NathanOliver How does the linked dup answer the question? Vote to reopen. – A M Nov 15 '22 at 16:18
  • The standard way is to define the custom swap() in the namespace of your special-needs type. Then, for calling from within a template, use `using namespace std; swap(u, v);` This shoudl then resolve to the swap() in the right namespace. As described here: https://en.cppreference.com/w/cpp/named_req/Swappable – Michaël Roy Nov 15 '22 at 16:47
  • @MichaëlRoy it is better to use `using std::swap;` in that case, rather than `using namespace std;` – Remy Lebeau Nov 15 '22 at 18:13
  • No. `using std::swap(); swap(u, v);` will make std::swap() rhe default and effectively hide swap functions from other namespaces. `using namespace std; swap(u, v);` will _default_to std::swap if an overloaded swap is not found in the namespace of the type being swapped. That's a big big difference. – Michaël Roy Nov 15 '22 at 18:27

1 Answers1

1

The standard requirement for "swappable types" is swap(t, u) where std::swap from the <utility> header is a viable candidate.

This is satisfied by both using namespace std; and if a using std::swap;. The standard way given is the latter (https://wg21.link/swappable.requirements#6):

#include <utility>

// Preconditions: std​::​forward<T>(t) is swappable with std​::​forward<U>(u).
template<class T, class U>
void value_swap(T&& t, U&& u) {
  using std::swap;
  swap(std::forward<T>(t), std::forward<U>(u)); // OK, uses “swappable with'' conditions
                                                // for rvalues and lvalues
}

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

For swapping two lvalues of the same type, you can also use std::iter_swap(std::addressof(a), std::adddressof(b)). This won't need a using-declaration.

See also: std::is_swappable.

This is separate from the C++20 concept swappable, which uses std::ranges::swap, though that might be what you want to use.

Artyer
  • 31,034
  • 3
  • 47
  • 75