Edu*_*yan 32 c++ namespaces compiler-errors argument-dependent-lookup
假设以下代码:
#include <iostream>
using namespace std;
namespace X
{
class A{};
void f(A a){}
void g(int a){}
}
int main()
{
X::A a;
f(a);
g(5);
}
Run Code Online (Sandbox Code Playgroud)
编译代码时,会发生以下编译错误:
main.cpp:在函数'int main()'中:
main.cpp:error:'g'未在此范围内声明
所以函数f编译得很完美,但事实g并非如此.怎么样?它们都属于同一名称空间.编译器是否从类型的参数中推断出该函数f属于X命名空间X::A?在这种情况下编译器如何表现?
tao*_*ocp 27
X::A a;
f(a);
Run Code Online (Sandbox Code Playgroud)
因为Argument-Dependent Lookup(也称为Koenig Lookup)而起作用.a是A命名空间内的类的对象X,当编译器搜索可匹配的函数时f,它将X在这种情况下查看命名空间.有关更多信息,请参阅参数依赖查找.
Sha*_*our 19
这适用于函数调用表达式:
f(a);
Run Code Online (Sandbox Code Playgroud)
因为X::A属于的命名空间f由于参数依赖查找(ADL)而包含在函数的查找中,所以cppreference解释ADL如下:
依赖于参数的查找(也称为ADL或Koenig查找)是用于在函数调用表达式中查找非限定函数名称的规则集,包括对重载运算符的隐式函数调用.除了通常的非限定名称查找所考虑的范围和名称空间之外,还会在其参数的名称空间中查找这些函数名称.
依赖于参数的查找使得可以使用在不同命名空间中定义的运算符
这在C++标准部分3.4.2 参数Argument依赖名称查找中有所介绍:
当函数调用(5.2.2)中的postfix-expression 是非限定id时,可以搜索在通常的非限定查找(3.4.1)期间未考虑的其他命名空间,并且在这些命名空间中,命名空间范围的朋友函数或函数可以找到不可见的模板声明(11.3)
接着说:
对于函数调用中的每个参数类型T,存在一组零个或多个关联的命名空间以及要考虑的一组零个或多个关联的类.命名空间和类的集合完全由函数参数的类型(以及任何模板模板参数的命名空间)决定.
并包括以下项目:
如果T是类类型(包括联合),则其关联的类是:类本身; 它所属的成员,如果有的话; 及其直接和间接基类.其关联的名称空间是其关联类是成员的名称空间.[...]
进一步向下提供了一个与您的问题类似的示例:
namespace NS {
class T { };
void f(T);
void g(T, int);
}
NS::T parm;
void g(NS::T, float);
int main() {
f(parm); // OK: calls NS::f
extern void g(NS::T, float);
g(parm, 1); // OK: calls g(NS::T, float)
}
Run Code Online (Sandbox Code Playgroud)
函数调用表达式:
g(5);
Run Code Online (Sandbox Code Playgroud)
不起作用,因为ADL不为基本类型的参数添加任何名称空间.
Herb Sutter在Gotw#30和什么是同类课程中涵盖了ADL ?- 接口原理.
| 归档时间: |
|
| 查看次数: |
1169 次 |
| 最近记录: |