你这样做是错的 :)
17.6.2.4.1 [命名空间.std]
std
如果 C++ 程序将声明或定义添加到命名空间或命名空间内的命名空间,则 C++ 程序的行为是未定义的,std
除非另有说明。std
只有当声明依赖于用户定义的类型并且特化满足原始模板的标准库要求并且没有明确禁止时,程序才能将任何标准库模板的模板特化添加到命名空间。
这很清楚地表明您可能不会向 namespace 添加重载std
。您可以专门std::swap<MyType>
针对您的类型,但如果您的类型是模板,则需要部分专门化,std::swap<MyContainer<T>>
并且您不能部分专门化函数模板,因此这不起作用,因此一般来说这不是一个好方法。
C++11 还定义了可交换类型的要求,包括:
17.6.3.2 [swappable.requirements]
- ...
- ...
swap(t, u)
评估和的上下文swap(u, t)
应确保通过重载决议(13.3)在候选集上选择名为“swap”的二进制非成员函数,该候选集包括:
<utility>
(20.2)中定义的两个交换函数模板和
- 由参数相关查找(3.4.2)产生的查找集。
因此调用swap
两个可交换类型的对象应该能够找到std::swap
并且应该能够通过 ADL 找到其他重载。将其称为不合格(并且没有显式模板参数列表)可确保 ADL 发生,并包含<utility>
并添加 using-declaration forstd::swap
确保可以找到标准重载。因此,按照您在问题中显示的方式进行操作符合这些要求。
这很清楚地定义了在标准使用的意义上可交换需要什么,这是标准库所要求的,例如<algorithm>
.
如果您将swap
类型的重载放在类型的命名空间中,那么 ADL 可以找到它们。无论如何,这是正确的做法,与您的类型相关的函数与您的类型属于同一命名空间,有关该主题的更多详细信息,请参阅 Sutter 和 Alexandrescu 的C++ 编码标准中的第 57 条。
所以简而言之,你做错了。你读的是正确的。执行using std::swap
和依赖 ADL 始终有效(对于模板和非模板)并避免未定义的行为。耶。
注意 C++03 标准对如何交换用户定义的类型不太清楚。有关该领域的一些历史,请参阅N1691 2.2,它定义了术语自定义点并显示了在 API 中定义它们的不同方法。C++11 中用于交换类型的协议使用了其中一种方式,现在被明确无误地祝福为为您的类型提供交换功能的“正确方式”。其他库中的其他自定义点可以使用其他方法,但在 C++11 术语中可交换意味着using std::swap;
并依赖于 ADL。