指向独立函数和友元函数的指针之间的区别

Jar*_*k C 19 c++ function-pointers friend-function

我不明白为什么以下不能编译(例如在 gcc 9.10 或 MS VS C++ 2019 中):

class X {
  public:
    friend bool operator==(int, X const &);
};

int main() {
  2 == X();  // ok...
  static_cast<bool (*)(int, X const &)>(&operator==);  // Error: 'operator==' not defined
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

但以下代码编译没有任何问题:

class X {
  public:
};
bool operator==(int, X const &);

int main() {
  2 == X();  // ok...
  static_cast<bool (*)(int, X const &)>(&operator==);  // OK!
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

我的期望是 X 的友元函数 (operator==) 表现为独立函数 (operator==)。我缺少什么?谢谢

Sto*_*ica 23

我缺少什么?

内联友元声明不会使该函数可用于普通名称查找。

密切注意错误。它并不是说该函数的类型错误,它只是找不到任何名为operator==. 这是设计使然。

内联友元定义只能通过参数相关查找找到。普通查找(如命名函数取其地址),找不到。如果您希望该函数可用于该目的,则必须提供命名空间范围的声明。

class X {
  public:
    friend bool operator==(int, X const &) { /* ... */ }
};

bool operator==(int, X const &);
Run Code Online (Sandbox Code Playgroud)


Waq*_*med 5

标准 11.9.3.7

如果这样的函数附加到全局模块,则它隐式为内联 ([dcl.inline]) 函数。在类中定义的友元函数在定义它的类的(词法)范围内。在类外定义的友元函数不是([basic.lookup.unqual])。

来自标准namespace.memdef/3 :(感谢@StoryTeller)

如果非局部类中的友元声明首先声明了类、函数、类模板或函数模板,则友元是最内部封闭命名空间的成员。友元声明本身不会使名称对非限定查找 ([basic.lookup.unqual]) 或限定查找([basic.lookup.qual]) 可见。[注意:如果在命名空间范围内(在授予友谊的类定义之前或之后)提供匹配声明,则朋友的名称将在其命名空间中可见。— end note ] 如果调用友元函数或函数模板,则可以通过名称查找找到它的名称,该名称查找考虑来自与函数参数类型相关的命名空间和类的函数([basic.lookup.argdep]). 如果友元声明中的名称既不是限定名称也不是模板 id 并且声明是函数或详细类型说明符,则确定实体之前是否已声明的查找不应考虑最内部封闭命名空间之外的任何范围.

以下不起作用,因为该函数在当前范围内不可见。

  static_cast<bool (*)(int, X const &)>(&operator==);  // Error: 'operator==' not defined
Run Code Online (Sandbox Code Playgroud)