"using std::swap" 如何启用 ADL?
How does "using std::swap" enable ADL?
在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
有什么用?
"enable 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
实现。
只是想补充一下为什么使用这个成语,这似乎是原始问题的精神。
许多 std 库 classes 中都使用了这个习语,其中实现了交换。来自 http://www.cplusplus.com/reference/algorithm/swap/:
Many components of the standard library (within std) call swap in an
unqualified manner to allow custom overloads for non-fundamental types
to be called instead of this generic version: Custom overloads of swap
declared in the same namespace as the type for which they are provided
get selected through argument-dependent lookup over this generic
version.
所以在你描述的函数中使用不合格的 "swap" 来交换成员变量的目的是为了让 ADL 可以找到那些 classes 的自定义交换函数(如果它们存在于其他地方)。
由于这些自定义的 classes 不存在于您引用的 class 中(mSize 和 mArray 在原始文件中分别是 std::size_t 和 int* example),并且 std::swap 工作得很好,作者添加了一条评论,说在这种情况下这不是必需的,但是很好的做法。如果他明确地调用 std::swap,他会得到相同的结果,正如前面的回答中所指出的那样。
为什么这是个好习惯?因为如果您有 classes 的成员实例,并为其定义了自定义交换,您希望行为是这样的:检查自定义交换函数...如果存在,则使用它,如果不存在,则使用它, 使用标准库函数。在没有可用的自定义交换功能的情况下,您希望它 默认 为上面 link 中描述的简单 std::swap 实现。因此 "using",将内置类型的交换带入命名空间。但这些将最后尝试。
另请参阅:
如果出于某种原因你讨厌 "using std::swap",我想你理论上可以通过显式调用 std::swap 来手动解决这个问题,使用 std::swap 和对您知道的每个自定义交换使用不合格的交换(仍然使用 ADL 找到)。但这很容易出错……如果您没有编写那些 classes,您可能不知道是否存在针对它的自定义交换。在 std::swap 和 swap 之间切换会使代码混乱。最好让编译器处理所有这些。
在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
有什么用?
"enable 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
实现。
只是想补充一下为什么使用这个成语,这似乎是原始问题的精神。
许多 std 库 classes 中都使用了这个习语,其中实现了交换。来自 http://www.cplusplus.com/reference/algorithm/swap/:
Many components of the standard library (within std) call swap in an unqualified manner to allow custom overloads for non-fundamental types to be called instead of this generic version: Custom overloads of swap declared in the same namespace as the type for which they are provided get selected through argument-dependent lookup over this generic version.
所以在你描述的函数中使用不合格的 "swap" 来交换成员变量的目的是为了让 ADL 可以找到那些 classes 的自定义交换函数(如果它们存在于其他地方)。
由于这些自定义的 classes 不存在于您引用的 class 中(mSize 和 mArray 在原始文件中分别是 std::size_t 和 int* example),并且 std::swap 工作得很好,作者添加了一条评论,说在这种情况下这不是必需的,但是很好的做法。如果他明确地调用 std::swap,他会得到相同的结果,正如前面的回答中所指出的那样。
为什么这是个好习惯?因为如果您有 classes 的成员实例,并为其定义了自定义交换,您希望行为是这样的:检查自定义交换函数...如果存在,则使用它,如果不存在,则使用它, 使用标准库函数。在没有可用的自定义交换功能的情况下,您希望它 默认 为上面 link 中描述的简单 std::swap 实现。因此 "using",将内置类型的交换带入命名空间。但这些将最后尝试。
另请参阅:
如果出于某种原因你讨厌 "using std::swap",我想你理论上可以通过显式调用 std::swap 来手动解决这个问题,使用 std::swap 和对您知道的每个自定义交换使用不合格的交换(仍然使用 ADL 找到)。但这很容易出错……如果您没有编写那些 classes,您可能不知道是否存在针对它的自定义交换。在 std::swap 和 swap 之间切换会使代码混乱。最好让编译器处理所有这些。