应用非限定名称查找,而不是依赖参数的名称查找
Unqualified name lookup applied instead of argument-dependent name lookup
考虑一个来自标准第3.4.3/3节的例子:
typedef int f;
namespace N
{
struct A
{
friend void f(A &);
operator int();
void g(A a)
{
int i = f(a);// f is the typedef, not the friend
// function: equivalent to int(a)
}
};
}
f(a)
为后缀表达式。编译器如何确定f(a)
不是一个函数调用?我想知道我们什么时候没有像f previously declared of typedef int f
那样的误差;如下例所示:
#include <stdio.h>
typedef int foo; //error: previous declaration of ‘typedef int foo’
class B
{
public:
friend void foo(B b){ printf("3"); } //error: ‘void foo(B)’ redeclared as different kind of symbol
static const int c=42;
};
int main(){ }
(在我的c++ 11文档版本中,示例在3.4.3中给出)。
3.4.3明确指出,为了进行解析,为了执行初始确定这是后缀表达式还是函数调用,执行通常的名称查找。"通常"意味着按照3.4.1其余部分的描述执行查找,并且在初始阶段不使用ADL。3.4.3明确指出"3.4.2中的规则对表达式的语法解释没有影响。"(3.4.2 is ADL).
在本例中,在解析f(a)
时,使用常规查找来查找名称f
。它查找全局类型定义-name ::f
,而没有其他任何内容。这意味着f(a)
被视为后缀表达式(强制类型转换),而不是函数调用。注意,A
中的函数f
的友元声明指向函数N::f
,但它没有在N
中引入N::f
的声明。由于N::f
函数没有在N
中显式声明(它在N
中不可见),因此通常的查找不会看到它。它只看到全局::f
,这是一个类型定义-name。
如果您希望使用通常的名称查找来查找第一个示例中的函数,则必须在N
中显式声明该函数
typedef int f;
namespace N
{
struct A; // <- added
void f(A &); // <- added
struct A
{
friend void f(A &);
...
现在N::f
的声明在N
中可见。现在,通常的名称查找将找到N::f
,并从一开始就将该f(a)
视为函数调用。
你的第二个例子与第一个有很大的不同。这里没有额外的名称空间。因此,B
中的友元函数声明引用全局::foo
,并声明foo
是一个函数。但是全局::foo
已经被声明为typedef-name。这个矛盾正是导致错误的原因。
相关文章:
- 参数相关查找和流运算符重载
- 编译器在C++中调用另一个函数时,在参数中查找已删除的构造函数
- 当数组在C++中用作参数时,查找数组的元素数
- C++ 普通查找与参数相关查找
- 运算符<<依赖于参数的查找不在全局命名空间中查找
- 查找可变参数列表的字符串格式指定符
- 在参数相关查找之前进行模板替换的任何方法(或解决方法?
- 如何查找/删除具有特定参数的结构向量的元素
- C 中的参数查找
- 支持与参数有关的查找的编译器
- 为什么在其他函数中声明的函数不参与参数相关查找?
- 使用查找表选择具有运行时索引的可变参数类型
- 为什么在这种情况下不考虑依赖于参数的查找?
- 数组作为函数参数查找数组长度时出错
- 仅通过参数查找重载地址
- 重载函数查找轮廓的实例与参数列表不匹配
- 我如何避免使用依赖于参数的查找明确专门化模板化功能
- 查找参数包的唯一值的数目
- 查找参数时出错
- 用于查找参数是否为类的不同模板语法