【问题标题】:Why does friend function found successfully via ADL为什么通过 ADL 成功找到好友功能
【发布时间】:2014-05-23 13:52:36
【问题描述】:

考虑以下代码:

#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());是函数调用的后缀表达式。

我很困惑……

【问题讨论】:

  • 你在标题中找到了答案。你到底在问什么?
  • 我会尽力说明这一点,希望我做对了。如果不让我知道,我会编辑。
  • @juanchopanza 因为 foo 对于通常的名称查找不可见。这意味着 ADL 不适用于 foo(A())。
  • @juanchopanza 据我所知,ADL 策略仅在通常的名称查找后应用。但是通常的名称查找找不到友元函数声明。
  • 在类体内定义的友元函数不在封闭类的范围内,它们在文件范围内

标签: c++ friend


【解决方案1】:

解析以下程序时

#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:将通过在其潜在参数(即A)定义的范围内搜索来找到foo。

朋友声明在您发布时引入了一个(可能不可见)名称 (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
}

您可能想要搜索“friend name injection”和/或Barton-Nackman trick。 短篇小说:现在普通查找找不到朋友声明。

因此,您发布的代码格式正确,因为 ADL 允许它按照我在前面段落中的说明运行。

【讨论】:

  • 你没有问我的问题。 foo 对于通常的名称查找是不可见的。
  • 或者澄清一下通常的名称查找是什么意思?
  • @DmitryFucintv 这是正常的名称查找(不是 ADL):stackoverflow.com/a/2604079/1938163。由于友元隐藏作用域,没有 ADL 就找不到 Foo,您可以将其视为子作用域。 ADL 表示 = 搜索参数范围的所有子范围。仔细阅读说明
猜你喜欢
  • 2016-02-18
  • 2020-06-04
  • 2021-07-29
  • 2021-01-09
  • 2012-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多