c++ - 为什么通过ADL成功找到 friend 功能

标签 c++ friend

考虑以下代码:

#include <stdio.h>

class A
{
public:
    friend void foo(A a){ printf("3\n"); }
};

int main()
{ 
    foo(A());
}

它有效。但我认为这段代码无效。这是因为 3.4.1/3:

For purposes of determining (during parsing) whether an expression is a postfix-expression for a function call, the usual name lookup rules apply.

通常的名称查找规则无法找到 friend 函数,因为在我的例子中,friend 声明的名称在全局命名空间中是不可见的。实际上 3.3.1/4:

friend declarations (11.3) may introduce a (possibly not visible) name into an enclosing namespace

这意味着程序格式错误。这是因为没有找到名字,在确定表达式foo(A());是一个函数调用的后缀表达式。

我很困惑......

最佳答案

解析如下程序时

#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

For purposes of determining (during parsing) whether an expression is a postfix-expression for a function call, the usual name lookup rules apply.

这意味着:要确定 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.

friend 声明在您发布 (3.3.1/4) 时引入了一个(可能不可见的)名字

friend declarations (11.3) may introduce a (possibly not visible) name into an enclosing namespace

这意味着下面的代码将不起作用

#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
}

您可能想要搜索“ friend 姓名注入(inject)”和/或 Barton-Nackman trick . 简短的故事:现在普通查找找不到友元声明。

所以您发布的代码格式正确,因为 ADL 允许它按照我在前面的段落中解释的那样运行。

关于c++ - 为什么通过ADL成功找到 friend 功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23831077/

相关文章:

c++ - 使用参数获取其他参数

c++ - 如果我在实现 (.cpp) 文件中定义一个函数而不在头文件中定义它会发生什么?

c++ - OSX 缺少 memalign

c++ - 如何将终止 NUL 字符\x00 转换为字符串?

c# - C Sharp 中的 'friend' 关键字等效于什么?

C++ 构造函数继承无法正常工作

c++ - 具有不同模板参数的相同类不能访问彼此的私有(private)字段

c++ - 一个简单类模板的c++17中的 friend 流运算符

C++:两个相互引用的类

c++ - 在命名空间中使用正确的语法实现非成员重载运算符