I would like to swap two arrays of ints of some fixed size.
Counterintuitively, the following does not compile because no matching instance of swap
has been found.
#include <array>
#include <utility>
int main()
{
std::array<int,3> a, b;
std::swap< std::array<int,3> >( a, b );
return 0;
}
I find this surprising. However, replacing the swap with std::swap(a,b)
compiles and (according to VSCode) has signature
inline void std::swap<int, 3UL>(std::array<int, 3UL> &__one, std::array<int, 3UL> &__two)
which I cannot make sense of either.
Q: What is going on here?
std::swap
is an overloaded function, not a function template. There is therefore no reason to assume thatstd::swap(T&, T&)
(for some typeT
) is callable asstd::swap<T>(x, y)
. — Of course if you want to implement an overload for a type template (such asstd::array
) you need to make the overload a template, too. But, again, it won’t be templated onT
; it will be templated on the template arguments of your type template. — Lastly, for generic typesT
you should not callstd::swap
viastd::swap(x, y)
! Instead, dousing std::swap; swap(x, y);
– Katushkastd::swap
being an overloaded function does not contradict it being a function template. Language standard explicitly listsstd::swap
variants along with their requirements. Basic varianttemplate<class T> void swap( T& a, T& b );
must be usable as long as T meets the requirements for MoveConstructible and MoveAssignable. So there is no reason to assume thatstd::swap<std::array<int,3>>
is not callable. – Infrequentswap
can be overfloaded and not all overloads use templates the same way, the recommended way to call it isusing std::swap; swap(a, b);
. This also allows for argument-dependent lookup (ADL) to findswap
functions outside ofnamespace std
. – Ician