Строка «template <>» в начале функции говорит о том, что это
class Widget { // все как раньше, за исключением
public: // добавления функции-члена swap
…
void swap(Widget& other)
{
using std::swap; // необходимость в этом объявлении
// объясняется далее
swap(pimpl, other.pimpl); // чтобы обменять значениями два объекта
} // Widget,обмениваем указатели pimpl
…
};
namespace std {
template <> // переделанная версия
void swap
Widget& b)
{
a.swap(b); // чтобы обменять значениями Widget,
} // вызываем функцию-член swap
}Этот вариант не только компилируется, но и полностью согласован с STL-контейнерами, каждый из которых предоставляет и открытую функцию-член swap, и специализированную версию std::swap, которая вызывает эту функцию-член. Предположим, однако, что Widget и Widgetlmpl – это не обычные, а
template class WidgetImpl {…}; template
Поместить функцию-член swap в Widget (и при необходимости в Widgetlmpl) в этом случае так же легко, как и раньше, но мы сталкиваемся с проблемой, касающейся специализации std::swap. Вот что мы хотим написать:
namespace std {
template
void swap
Widget
{ a.swap(b);}
}Выглядит совершенно разумно, но все равно неправильно. Мы пытаемся частично специализировать шаблон функции (std::swap), но, хотя C++ допускает частичную специализацию шаблонов класса, он не разрешает этого для шаблонов функций. Этот код не должен компилироваться (если только некоторые компиляторы не пропустят его по ошибке). Когда вам нужно «частично специализировать» шаблон функции, лучше просто добавить перегруженную версию. Примерно так:
namespace std {
template
void swap(Widget
Widget
{ a.swap(b);} // “swap”), далее объяснено, почему
} // этот код некорректен