为什么std::swap不在全局命名空间中?

3
Effective c++第三版的第25条建议中,Scott Meyers建议在与类相同的命名空间中实现swap函数,然后在交换时使用using std :: swap,并且作者在此处说:

For example, if you were to write the call to swap this way:

std::swap(obj1,obj2);  // the wrong way to call swap

you'd force the compiler to consider only the swap in std, thus eliminating the possibility of getting a more appropriate T-specific version defined elsewhere. Alas, some misguided programmers do qualify calls to swap in this way, and that is why it's important to totally specialize std::swap for your classes.

作者建议始终以这种方式交换对象:
#include <iostream>
#include <utility>

#define CUSTOM_SWAP

namespace aaa{

struct A
{
};
#ifdef CUSTOM_SWAP
void swap( A&, A& )
{
    std::cout<<"not std::swap"<<std::endl;
}
#endif

}

int main() 
{
    using std::swap;   // add std::swap to a list of possible resolutions

    aaa::A a1;
    aaa::A a2;

    swap(a1,a2);
}

为什么 std::swap 不在全局命名空间中?这样,就可以更简单地添加自定义的交换功能。

3
因为它会妨碍你,即使你不想要它出现? - jrok
@jrok 好的,我猜当你实现模板时它会妨碍你,对吧? - BЈовић
或者不这样做。假设您想为某个具体类型调用自己的全局swap,并期望在传递其他类型时无法编译。如果在全局范围内使用swap模板,则仍会编译。 - jrok
1
还有一件事:如果从Meyers的文章中你学到了“永远不要写std::swap(x,y);”,那么我敢说这是一个错误的教训。如果你知道你想调用std::swap,那么请明确地调用它。 - jrok
@jrok 有人使用我的类可能不知道它有一个专门的交换功能。无论如何,catscradle 在评论中回答了我的问题。 - BЈовић
显示剩余2条评论
1个回答

7

可能是因为标准规定如此,17.6.1.1/2:

除宏、operator new和operator delete之外的所有库实体都定义在命名空间std或位于命名空间std内部的命名空间中。

有时仍需要使用using ::swap,这会引入更多特殊情况。在这里,我使用func代替swap - http://ideone.com/WAWBfZ

#include <iostream>
using namespace std;

template <class T>
auto func(T) -> void
{
cout << "::f" << endl;
}

namespace my_ns {
struct my_struct {};

auto func(my_struct) -> void
{
cout << "my_ns::func" << endl;
}

auto another_func() -> void
{
// won't compile without `using ::func;`
func(123);
}
}

auto main() -> int {}

无法通过

prog.cpp: In function ‘void my_ns::another_func()’:
prog.cpp:21:17: error: could not convert ‘123’ from ‘int’ to ‘my_ns::my_struct’
         func(123);

点赞,因为“标准的 bitchslap” 总是很好看。 - Alec Teal
1
我的问题是:为什么标准规定swap应该在std命名空间中? - BЈовић
@BЈовић swap 是标准库的一部分。为什么要把它作为一个特殊情况呢? - catscradle
根据Scott Meyers的说法,您应该始终使用using std::swap。这就是为什么。 - BЈовић
@BЈовић 这个习语在编写通用模板代码时使用。其思想是为提供了专门的swap函数的类型使用它(因为这样可能会针对其情况进行优化),否则回退到std::swap。 OP中的代码并不是一个很好的例子。 - jrok
2
@BЈовић 你仍然需要有时候放置 using ::swap,这样会引入更多的特殊情况。在这里我使用 func 而不是 swap - http://ideone.com/WAWBfZ。 - catscradle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接