与朋友一起而不是向前声明的类:哪个编译器正确

Ren*_*ger 6 c++ gcc cl

我有这个简单的C ++程序:

#include <iostream>

struct obj {
  friend int f(int);

  void m(int x) { std::cout << "f(" << x << ") = " << f(x) << std::endl; }
};

int main() {
  obj o;
  o.m(21);
}


int f(int x) {
  return 2*x;
}
Run Code Online (Sandbox Code Playgroud)

如果我使用GNU C ++编译器进行编译g++则会收到错误prog.cpp:7:55:错误:未在此范围内声明'f'

但是,如果我使用cl(和/W4)对其进行编译,则它将编译并执行良好。

我不确定哪个编译器正确。

lub*_*bgr 3

来自友元声明的 cppreference :

首先在类或类模板 X 中的友元声明中声明的名称将成为 X 的最内层封闭命名空间的成员,但对于查找不可见(除了考虑 X 的参数相关查找之外),除非命名空间范围内的匹配声明是假如

提供了全局范围内的匹配声明,但仅在的定义之后obj::m()f我认为此时拒绝电话是正确的。您可以看到效果,例如使用gcc和进行编译clang

int f(int);

class obj { /* as before... */ };
Run Code Online (Sandbox Code Playgroud)

这也是如此:

struct obj {
  friend int f(int);

  void m(int x); 
};

int f(int);

void obj::m(int x) { std::cout << "f(" << x << ") = " << f(x) << std::endl; }
Run Code Online (Sandbox Code Playgroud)