背景
考虑以下代码:
#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
}
Now 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
}
Question
Does std::swap
采取的行为boost::swap
在 C++11 中?如果没有,为什么?
对我来说,显然应该这样做。任何因更改而损坏的代码一开始都可能非常脆弱(算法和容器,例如std::sort
and std::vector
,未指定;实现被允许调用 ADL 交换(或者不是不确定的),所以这个改变会更好。此外,std::swap
现在是为数组定义的,所以完全改变当然不是不可能的。
然而,虽然 §17.6.3.2 指定所有调用swap
在标准库内必须完成std::
资格(解决上面提到的算法和容器的问题),它没有触及std::swap
本身。它甚至给出了交换值的示例,包括using std::swap;
。同样§20.2.2(其中std::swap
已指定)没有提及 ADL。
最后,GCC 并未在其系统中启用 ADLstd::swap
实现(MSVC 也没有,但这并没有说明太多)。所以我一定是错的std::swap
采取的行为boost::swap
,但我不明白为什么没有做出改变。 :(我并不孤单 https://stackoverflow.com/a/6115281/87234!