Вопрос по boost:: swap

Пара вопросов по boost::swap. Пожалуйста, обратитесь к приведенному ниже коду, который в основном представляет собой вырезную пасту из boost/swap.hpp. Я имею в виду версию библиотеки 1.43.0.

namespace boost_swap_impl
    {
      template<class T>
      void swap_impl(T& left, T& right)
      {
        using namespace std;//use std::swap if argument dependent lookup fails
        swap(left,right);
      }

  template<class T, std::size_t N>
  void swap_impl(T (& left)[N], T (& right)[N])
  {
    for (std::size_t i = 0; i < N; ++i)
    {
      ::boost_swap_impl::swap_impl(left[i], right[i]);
    }
  }
}

namespace boost
{
  template<class T1, class T2>
  void swap(T1& left, T2& right)
  {
    ::boost_swap_impl::swap_impl(left, right);
  }
}
  • Почему boost::swap объявлен как template <typename T1, typename T2>, когда в остальной части кода все работает с одним и тем же типом?
  • Если я определяю свою собственную глобальную функцию void swap(T&, T&), я вижу, что глобальная функция вызывается из swap_impl(T& left, T& right). Разве это не конфликт и, следовательно, условие ошибки, так как swap_impl также использует namespace std, который имеет swap?

Ответ 1

  • Это делает его менее специализированным, чем std::swap, поэтому вы не получаете ошибок неоднозначности при перегрузке, когда в std::swap и boost::swap присутствуют (std::swap).
  • Нет, не-шаблоны всегда имеют приоритет над шаблонами во время разрешения перегрузки, поэтому не-шаблон swap с пространством имен будет иметь приоритет как для boost::swap, так и std::swap (как и шаблон с областью имен swap перегружен для UDT, думаю, частично-специализированный, но не совсем.). Обратите внимание, что в отличие от std::swap, boost::swap явно написано, чтобы воспользоваться ADL.

Вот что должен сказать стандарт С++ 03 относительно обеих точек – [over.match.best] (§13.3.3/1):

Определите ICS i (F) следующим образом:

  • Если F является статической функцией-членом, ICS 1 (F) определяется так, что ICS 1 (F) не лучше и не хуже чем ICS 1 (G) для любой функции G, и, симметрично, ICS 1 (G) не лучше и не хуже, чем ICS 1 (F); в противном случае,
  • пусть ICS i (F) обозначает неявную последовательность преобразований, которая преобразует i-й аргумент в список в тип i-го параметра жизнеспособной функции F. 13.3.3.1 определяет неявные последовательности преобразований, а 13.3.3.2 определяет, что означает, что одна неявная последовательность преобразований является лучшей последовательностью преобразования или худшей последовательностью преобразования, чем другая.

Учитывая эти определения, жизнеспособная функция F1 определяется как лучшая функция, чем другая жизнеспособная функция F2, если для всех аргументов i, ICS i (F1) не является хуже, чем ICS i (F2), а затем

  • для некоторого аргумента j, ICS j (F1) является лучшей последовательностью преобразования, чем ICS j (F2), или, если не тот,
  • F1 - это не шаблонная функция, а F2 - специализированная функция шаблона или, если не это,
  • F1 и F2 - специализированные шаблоны шаблонов функций, а шаблон функции для F1 более специализирован, чем шаблон для F2 в соответствии с правилами частичного упорядочения, описанными в 14.5.5.2, или, если это не так
  • контекст представляет собой инициализацию путем пользовательского преобразования (см. 8.5, 13.3.1.5 и 13.3.1.6) и стандартную последовательность преобразования из возвращаемого типа F1 в тип назначения (т.е. тип объект, инициализированный) является лучшей последовательностью преобразования, чем стандартная последовательность преобразования из возвращаемого типа F2 в тип назначения.