内联友元函数的范围是什么?

2022-01-04 00:00:00 inline scope c++ friend

在搜索完 SO 之后,一个问题告诉我内联友元函数的 词法 范围是它在其中定义的类,这意味着它可以访问例如类中的 typedef 没有限定它们.但后来我想知道这样一个函数的实际范围是什么? GCC 至少拒绝了我调用它的所有尝试.是否可以通过 ADL 以外的方式调用示例中的函数,由于没有参数,这在此处是不可能的?

After searching aroung SO, one question taught me that the lexical scope of an inline friend function is the class it's defined in, meaning it can access e.g. the typedefs in the class without qualifying them. But then I wondered what is the actual scope of such a function? GCC at least rejects all my attempts to call it. Can a function such as in the example ever be called through means other than ADL, which is not possible here thanks to no arguments?

感谢标准报价,因为我目前无法访问我的副本.

Standard quotations are appreciated, as I currently can't access my copy of it.

以下代码

namespace foo{
  struct bar{
    friend void baz(){}
    void call_friend();
  };
}

int main(){
  foo::baz();           // can't access through enclosing scope of the class
  foo::bar::baz();    // can't access through class scope
}

namespace foo{
  void bar::call_friend(){
    baz();    // can't access through member function
  }
}

导致这些错误:

prog.cpp: In function ‘int main()’:
prog.cpp:9: error: ‘baz’ is not a member of ‘foo’
prog.cpp:10: error: ‘baz’ is not a member of ‘foo::bar’
prog.cpp: In member function ‘void foo::bar::call_friend()’:
prog.cpp:15: error: ‘baz’ was not declared in this scope

推荐答案

当你在一个类中声明一个带有非限定 id 的 friend 函数时,它会在最近的封闭命名空间范围内命名一个函数.

When you declare a friend function with an unqualified id in a class it names a function in the nearest enclosing namespace scope.

如果之前没有声明过该函数,则 friend 声明不会使该函数在该范围内可见以进行正常查找.它确实使声明的函数对依赖于参数的查找可见.

If that function hasn't previously been declared then the friend declaration doesn't make that function visible in that scope for normal lookup. It does make the declared function visible to argument-dependent lookup.

许多注释都强调了这一点,但最终声明在 7.3.1.2/3(ISO/IEC 14882:2011)中:

This is emphasised in many notes, but the definitive statement is in 7.3.1.2/3 (of ISO/IEC 14882:2011):

首先在命名空间中声明的每个名称都是该命名空间的成员.如果非局部类中的 friend 声明 first 声明了一个类或函数,则友元类或函数是最内部封闭命名空间的成员.在该命名空间范围内提供匹配声明之前,通过非限定查找 (3.4.1) 或限定查找 (3.4.3) 找不到朋友的名称(在类定义之前或之后给予友谊).如果调用友元函数,则可以通过名称查找找到它的名称,该名称查找考虑来自与函数参数类型相关的命名空间和类的函数(3.4.2).如果friend 声明中的名称既不是限定名也不是模板id,并且声明是函数或详细类型说明符,确定实体是否先前已声明的查找不应考虑最内部封闭命名空间之外的任何范围.

Every name first declared in a namespace is a member of that namespace. If a friend declaration in a non-local class first declares a class or function the friend class or function is a member of the innermost enclosing namespace. The name of the friend is not found by unqualified lookup (3.4.1) or by qualified lookup (3.4.3) until a matching declaration is provided in that namespace scope (either before or after the class definition granting friendship). If a friend function is called, its name may be found by the name lookup that considers functions from namespaces and classes associated with the types of the function arguments (3.4.2). If the name in a friend declaration is neither qualified nor a template-id and the declaration is a function or an elaborated-type-specifier, the lookup to determine whether the entity has been previously declared shall not consider any scopes outside the innermost enclosing namespace.

相关文章