Consider the code:
#include <iostream>
#include <algorithm> // std::swap C++98
#include <utility> // std::swap C++11
namespace A
{
template<typename T>
struct Foo {};
template<typename T>
void swap(Foo<T> &lhs, Foo<T> &rhs)
{
std::cout << "A::swap<T>" << std::endl;
}
} /* end namespace A */
namespace std // we explicitly specialize std::swap here
{
template<> // explicit template specialization for std::swap<int>
void swap(A::Foo<int> &lhs, A::Foo<int> &rhs)
noexcept
(is_nothrow_move_constructible<A::Foo<int>>::value && is_nothrow_move_assignable<A::Foo<int>>::value)
{
std::cout << "std::swap<int>" << std::endl;
}
} /* end namespace std */
int main()
{
using std::swap;
A::Foo<int> a, b;
A::Foo<double> x, y;
swap(a, b); // ADL, expected to call std::swap<Foo<int>>, but NO
swap(x, y); // ADL, expected to call A::swap<T>, YES
}
I would expect the std::swap
explicit specialization to be a better candidate in the call swap(a, b)
, however it seems that the overload A::swap
is always preferred, i.e. the output is:
A::swap<T> A::swap<T>
Can anyone explain why this behaviour?
Explicit function template specializations never change which function template or overload is called, only the implementation of the template if it is called.
Overload resolution ignore specializations (as opposed to overloads, which can look a lot like partial specialization to someone unfamiliar with C++ function template quirks).
I can imagine why: mixing both overload and template specialization selection rules would make the rules even harder to follow and get right.
In general, it is rarely a good idea to specialize a function template: overloads, or dispatching to a template class, is usually better.
Note that the language talks about 'more specialized' in overload resolution: do not confuse this with 'template specialization': they are distinct concepts that unfortunetally share a word.