Фон
Рассмотрим для этого вопроса следующий код:
#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);
}
В С++ 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
в С++ 11? Если нет, то почему?
Мне кажется очевидным, что это должно быть. Любой код, нарушенный изменением, был, по-видимому, довольно хлипким (алгоритмы и контейнеры, такие как std::sort
и std::vector
), были недоказаны: реализациям разрешалось вызывать ADL-swap или неопределенно), поэтому изменение было бы для лучше. Кроме того, 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
, но я не понимаю, почему это изменение не было сделано.:(И я не одинок!