请考虑以下代码:
#include <stdio.h>
class A
{
public:
friend void foo(A a){ printf("3\n"); }
};
int main()
{
foo(A());
}
有效。但我认为这段代码无效。这是因为3.4.1 / 3:
用于确定(在解析期间)表达式是否为 函数调用的后缀表达式,通常的名称查找规则 应用
通常的名称查找规则找不到友元函数,因为朋友声明的名称在我的情况下在全局命名空间中是不可见的。实际上3.3.1 / 4:
朋友声明(11.3)可能会引入(可能不可见)名称 进入封闭的命名空间
这意味着该程序是不正确的。这是因为在确定期间找不到名称foo(A());
是函数调用的后缀表达式。
我很困惑......
答案 0 :(得分:4)
解析以下程序时
#include <iostream>
using namespace std;
typedef int foo;
class A
{
public:
operator int(){
return 42;
}
};
int main()
{
cout << foo(A());
}
输出为42
因为3.4.1 / 3
用于确定(在解析期间)表达式是否为 函数调用的后缀表达式,通常的名称查找规则 应用
这意味着:要确定foo
是否是后缀表达式(例如强制转换)或函数调用,编译器将首先使用名称查找并在全局命名空间中搜索它和/或封闭范围/基类(或完全限定的查找,如果可用)。
现在拿这段代码:
#include <iostream>
using namespace std;
class A
{
public:
friend int foo(A a){ return 55; }
operator int(){
return 42;
}
};
int main()
{
cout << foo(A());
}
由于ADL,上面将输出55
:foo将通过在其潜在参数定义的范围内搜索,即A。
朋友声明会在您发布(3.3.1 / 4)
时引入(可能不可见)名称朋友声明(11.3)可能会引入(可能不可见)名称 进入封闭的命名空间
这意味着以下代码无效
#include <iostream>
using namespace std;
class A
{
public:
friend int foo(A a){ return 55; }
operator int(){
return 42;
}
};
int main()
{
cout << ::foo(A()); // Not found
cout << A::foo(A()); // Not found
}
您可能想要搜索&#34; 朋友名称注入&#34;和/或Barton-Nackman trick。 简短的故事:现在普通的查找无法找到朋友声明。
因此,您发布的代码格式正确,因为ADL允许它按照我在前面的段落中解释的那样运行。