"如何使用std :: swap"启用ADL?

时间:2015-01-24 21:52:49

标签: c++ c++11 argument-dependent-lookup

What is the copy-and-swap idiom中显示了此示例:

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是什么?

2 个答案:

答案 0 :(得分:10)

“启用ADL”注释适用于

的转换
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实现。

答案 1 :(得分:10)

只想添加为什么会使用这个习语,这似乎是原始问题的精神。

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

  

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

因此,在您描述的函数中使用非限定“swap”交换成员变量的目的是让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之间切换会使代码混乱。最好让编译器处理所有这些。