Фон
Рассмотрим для этого вопроса следующий код:
#include <utility>
namespace ns
{
struct foo
{
foo() : i(0) {}
int i;
private:
foo(const foo&); // not defined,
foo& operator=(const foo&); // non-copyable
};
void swap(foo& lhs, foo& rhs)
{
std::swap(lhs.i, rhs.i);
}
}
template <typename T>
void do_swap(T& lhs, T& rhs); // implementation to be determined
int main()
{
ns::foo a, b;
do_swap(a, b);
}
В C ++ 03 эта реализация do_swap
будет считаться "сломанной":
template <typename T>
void do_swap(T& lhs, T& rhs)
{
std::swap(lhs, rhs);
}
Явно указав std::
, он запрещает поиск ns::swap
через поиск, зависящий от аргумента.(Затем он не скомпилируется, потому что std::swap
пытается скопировать foo
, что недопустимо.) Вместо этого мы делаем это:
template <typename T>
void do_swap(T& lhs, T& rhs)
{
using std::swap; // allow std::swap as a backup if ADL fails to find a swap
swap(lhs, rhs); // unqualified call to swap, allow ADL to operate
}
Теперь ns::swap
найден и std::swap
,будучи менее специализированным, не используется.Это уродливее, но работает и понятно задним ходом.boost::swap
приятно оборачивает это для нас (и обеспечивает перегрузки массивов):
#include <boost/swap.hpp>
template <typename T>
void do_swap(T& lhs, T& rhs)
{
boost::swap(lhs, rhs); // internally does what do_swap did above
}
Вопрос
Мой вопрос, таким образом, : принимает ли std::swap
поведение boost::swap
в C ++ 11?Если нет, то почему?
Мне кажется очевидным, что так и должно быть.Любой код, нарушенный этим изменением, был, во-первых, довольно неубедительным (алгоритмы и контейнеры, такие как std::sort
и std::vector
, были недоопределены; реализациям разрешалось вызывать своп ADL или нет), поэтому изменение было бы длялучше.Кроме того, std::swap
теперь определено для массивов, поэтому об изменениях вообще не может быть и речи.
Однако, хотя в §17.6.3.2 указано, что все вызовы swap
в стандартной библиотеке должныбыть сделано без квалификации std::
(устранение проблемы с алгоритмами и контейнерами, указанными выше), он не затрагивает сам std::swap
.Он даже приводит примеры перестановки значений, которые включают using std::swap;
.Аналогично §20.2.2 (где указано std::swap
) не говорит ни слова о ADL.
Наконец, GCC не включает ADL в их реализации std::swap
(как и MSVC, но это не говорит о том, чтомного).Поэтому я, должно быть, ошибаюсь, что std::swap
принимает поведение boost::swap
, но я не понимаю, почему изменение не было сделано.:( И я не одинок !