“使用 std::swap”如何启用参数依赖查找(ADL)?

问题描述 投票:0回答:2

什么是复制和交换习惯用法中显示了这个示例:

friend void swap(dumb_array& first, dumb_array& second) // nothrow
{
    // enable ADL (not necessary in our case, but good practice)
    using std::swap; 

    // by swapping the members of two classes,
    // the two classes are effectively swapped
    swap(first.mSize, second.mSize); 
    swap(first.mArray, second.mArray);
}

using std::swap
究竟如何启用 ADL? ADL 仅需要非限定名称。我认为
using std::swap
的唯一好处是,由于
std::swap
是一个函数模板,您可以在调用中使用模板参数列表 (
swap<int, int>(..)
)。

如果不是这样,那么

using std::swap
是做什么用的?

c++ c++11 argument-dependent-lookup copy-and-swap
2个回答
24
投票

只是想补充一下为什么使用这个习语,这似乎是原始问题的精神。

这个习惯用法在许多实现交换的 std 库类中使用。来自 http://www.cplusplus.com/reference/algorithm/swap/:

标准库的许多组件(在 std 内)调用交换 允许非基本类型自定义重载的非限定方式 被调用而不是这个通用版本:交换的自定义重载 在与提供它们的类型相同的命名空间中声明 通过对此泛型进行参数相关的查找来选择 版本。

因此,使用非限定的“交换”来交换您所描述的函数中的成员变量的目的是,ADL 可以找到这些类的自定义交换函数(如果它们存在于其他地方)。

由于这些自定义类在您引用的类中不存在(在原始示例中,mSize 和 mArray 分别是 std::size_t 和 int*),并且 std::swap 工作得很好,因此作者补充说,在这种情况下这不是必需的,但良好的做法。如果他明确调用 std::swap,他会得到相同的结果,正如前面的答案中指出的那样。

为什么这是好的做法?因为如果您有定义了自定义交换的类的成员实例,您希望行为是这样的:检查自定义交换函数...如果存在,则使用它,如果不存在,则使用 std 库功能。在没有可用的自定义交换函数的情况下,您希望它“默认”为上面链接中描述的简单 std::swap 实现。因此,“使用”将内置类型的交换引入命名空间。但那些将在最后尝试。 另请参阅:

https://stackoverflow.com/a/2684544/2012659

如果出于某种原因你讨厌“使用 std::swap”,我想理论上你可以通过显式调用 std::swap 来手动解决这个问题,方法是使用 std::swap 并使用不合格的交换来交换所有内容对于您知道的每个自定义交换都已定义(仍然可以使用 ADL 找到)。但这很容易出错......如果您没有编写这些类,您可能不知道是否存在定制的交换。在 std::swap 和 swap 之间切换会导致代码混乱。最好让编译器处理所有这些。


18
投票
的转换

std::swap(first.mSize, second.mSize); std::swap(first.mArray, second.mArray);

using std::swap; swap(first.mSize, second.mSize); swap(first.mArray, second.mArray);

你是对的,ADL 仅需要非限定名称,但这就是重新编写代码以使用非限定名称的方式。

简单粗暴

swap(first.mSize, second.mSize); swap(first.mArray, second.mArray);

不起作用,因为对于许多类型,ADL 找不到 
std::swap

,并且范围内没有其他可用的

swap
实现。
    

© www.soinside.com 2019 - 2024. All rights reserved.