ADL 名称查找问题,正在使用 std::swap; swap(a,b) 与函数重载或内部作用域函数隐藏外部作用域函数有关?
ADL name lookup problem, is using std::swap; swap(a,b) related to function overloading or inner scope function hide outer scope function?
我知道 ADL 是什么,我知道在 C++ 中,内部作用域函数隐藏外部作用域函数。也就是说,名称不会跨范围超载。所以函数重载需要在相同的范围内完成。
所以现在我的问题是,对于这个通用代码片段:
#include <iostream>
#include <string>
using std::cout;
using std::endl;
namespace Foo{
class Bar{
friend void swap(Bar& a, Bar& b);
};
void swap(Bar& a, Bar& b){
cout << "I am here" << endl;
}
}
int main(int argc, char *args[]){
Foo::Bar a, b;
using std::swap; //These 2 lines
swap(a, b); //output is "I am here", Foo::swap is called
}
连同 ADL,是:
自定义swap
和std::swap
都可见,认为是重载,然后选择最匹配的?
首先找到自定义 swap
,然后名称查找停止(std::swap
已隐藏)?
如果 1.
为真,它是如何工作的?函数重载超过 2 个不同的范围?这与我开头写的矛盾。 using std::swap
将 std::swap
引入当前范围。自定义 swap
在 Foo::swap
中。
顺便说一句,这个答案What is “Argument-Dependent Lookup” (aka ADL, or “Koenig Lookup”)?似乎表明它们是函数重载。
Further, if for some reason both A::swap(A::MyClass&, A::MyClass&)
and
std::swap(A::MyClass&, A::MyClass&)
are defined, then the first
example will call std::swap(A::MyClass&, A::MyClass&)
but the second
will not compile because swap(obj1, obj2)
would be ambiguous.
如果是函数重载,为什么我的swap(Bar& a, Bar& b)
没有有他描述的歧义问题?他错了吗?
如果2.
为真,根据C++ Primer 5th 18.2.3:
std::cin >> s;
is equivalent to:
operator>>(std::cin, s);
In this example, when the compiler sees the “call” to operator>>
, it
looks for a matching function in the current scope, including the
scopes enclosing the output statement. In addition, because the >>
expression has parameters of class type, the compiler also looks in
the namespace(s) in which the types of cin
and s
are defined. Thus,
for this call, the compiler looks in the std
namespace, which defines
the istream
and string
types. When it searches std
, the compiler finds
the string
output operator function.
因此名称查找顺序为:当前范围 --> 封闭范围 --> 参数名称空间范围.
那为什么 std::swap
不隐藏自定义 swap
? using std::swap
将 std::swap
引入当前范围,它具有更高的查找优先级。
我的两个假设在某些部分似乎都无效,我感到很困惑。需要一些帮助。提前致谢。
1.
是真的。对于 ADL、
These function names are looked up in the namespaces of their arguments in addition to the scopes and namespaces considered by the usual unqualified name lookup.
std::swap
是通过通常的非限定名称查找找到的,而 Foo::swap
是通过 ADL 找到的,它们都在重载集中。 Foo::swap
是一个非模板函数,优先于 std::swap
,后者是 overload resolution.
中的模板
F1 is determined to be a better function than F2 if implicit
conversions for all arguments of F1 are not worse than the implicit
conversions for all arguments of F2, and
...
4) or, if not that, F1 is a non-template function while F2 is a
template specialization
关于链接答案中的引述,
if for some reason both A::swap(A::MyClass&, A::MyClass&)
and std::swap(A::MyClass&, A::MyClass&)
are defined,
实际上没有std::swap(A::MyClass&, A::MyClass&)
,这只是一个假设,如果有一个非模板std::swap(A::MyClass&, A::MyClass&)
那么调用就会有歧义 ...
我知道 ADL 是什么,我知道在 C++ 中,内部作用域函数隐藏外部作用域函数。也就是说,名称不会跨范围超载。所以函数重载需要在相同的范围内完成。
所以现在我的问题是,对于这个通用代码片段:
#include <iostream>
#include <string>
using std::cout;
using std::endl;
namespace Foo{
class Bar{
friend void swap(Bar& a, Bar& b);
};
void swap(Bar& a, Bar& b){
cout << "I am here" << endl;
}
}
int main(int argc, char *args[]){
Foo::Bar a, b;
using std::swap; //These 2 lines
swap(a, b); //output is "I am here", Foo::swap is called
}
连同 ADL,是:
自定义
swap
和std::swap
都可见,认为是重载,然后选择最匹配的?首先找到自定义
swap
,然后名称查找停止(std::swap
已隐藏)?
如果 1.
为真,它是如何工作的?函数重载超过 2 个不同的范围?这与我开头写的矛盾。 using std::swap
将 std::swap
引入当前范围。自定义 swap
在 Foo::swap
中。
顺便说一句,这个答案What is “Argument-Dependent Lookup” (aka ADL, or “Koenig Lookup”)?似乎表明它们是函数重载。
Further, if for some reason both
A::swap(A::MyClass&, A::MyClass&)
andstd::swap(A::MyClass&, A::MyClass&)
are defined, then the first example will callstd::swap(A::MyClass&, A::MyClass&)
but the second will not compile becauseswap(obj1, obj2)
would be ambiguous.
如果是函数重载,为什么我的swap(Bar& a, Bar& b)
没有有他描述的歧义问题?他错了吗?
如果2.
为真,根据C++ Primer 5th 18.2.3:
std::cin >> s;
is equivalent to:
operator>>(std::cin, s);
In this example, when the compiler sees the “call” to
operator>>
, it looks for a matching function in the current scope, including the scopes enclosing the output statement. In addition, because the>>
expression has parameters of class type, the compiler also looks in the namespace(s) in which the types ofcin
ands
are defined. Thus, for this call, the compiler looks in thestd
namespace, which defines theistream
andstring
types. When it searchesstd
, the compiler finds thestring
output operator function.
因此名称查找顺序为:当前范围 --> 封闭范围 --> 参数名称空间范围.
那为什么 std::swap
不隐藏自定义 swap
? using std::swap
将 std::swap
引入当前范围,它具有更高的查找优先级。
我的两个假设在某些部分似乎都无效,我感到很困惑。需要一些帮助。提前致谢。
1.
是真的。对于 ADL、
These function names are looked up in the namespaces of their arguments in addition to the scopes and namespaces considered by the usual unqualified name lookup.
std::swap
是通过通常的非限定名称查找找到的,而 Foo::swap
是通过 ADL 找到的,它们都在重载集中。 Foo::swap
是一个非模板函数,优先于 std::swap
,后者是 overload resolution.
F1 is determined to be a better function than F2 if implicit conversions for all arguments of F1 are not worse than the implicit conversions for all arguments of F2, and
...
4) or, if not that, F1 is a non-template function while F2 is a template specialization
关于链接答案中的引述,
if for some reason both
A::swap(A::MyClass&, A::MyClass&)
andstd::swap(A::MyClass&, A::MyClass&)
are defined,
实际上没有std::swap(A::MyClass&, A::MyClass&)
,这只是一个假设,如果有一个非模板std::swap(A::MyClass&, A::MyClass&)
那么调用就会有歧义 ...