c++ - 有关使用好友功能查找姓名的问题

标签 c++ c++17 language-lawyer friend name-lookup

我已经阅读了[basic.lookup.unqual]的标准部分,对此我感到困惑:

typedef int f;
namespace N {
  struct A {
    friend void f(A &);
    operator int();
    void g(A a) {
      int i = f(a);  // f is the typedef, not the friend function: equivalent to int(a)
    }
  };
}

请考虑上面的代码;我不明白为什么f名称是int类型,而不是void f(A &)类型。以我的理解,名称查找应该首先在类范围A中找到void f(A &)。如果在那里找不到名称,它将在外部 namespace 中执行查找。显然,在void f(A &)类中有一个名称A,正如标准所说:

name lookup ends as soon as a declaration is found for the name



那么,如果还有其他特定的规则,为什么名称会在此处引用int类型呢?

最佳答案

首先,friend declaration本身不会使f对于名称查找可见,f只能由ADL找到。

A name first declared in a friend declaration within class or class template X becomes a member of the innermost enclosing namespace of X, but is not visible for lookup (except argument-dependent lookup that considers X) unless a matching declaration at the namespace scope is provided



根据标准[namespace.memdef]/3

The friend declaration does not by itself make the name visible to unqualified lookup or qualified lookup. [ Note: The name of the friend will be visible in its namespace if a matching declaration is provided at namespace scope (either before or after the class definition granting friendship). — end note ] If a friend function or function template 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 ([basic.lookup.argdep]). 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.



问题是要应用ADL,必须事先确定f(a)是否为函数调用。

[basic.lookup.unqual]/3

(强调我的)

The lookup for an unqualified name used as the postfix-expression of a function call is described in [basic.lookup.argdep]. [ Note: For purposes of determining (during parsing) whether an expression is a postfix-expression for a function call, the usual name lookup rules apply.



在此阶段,函数名称f是不可见的,并且找到类型名称f,然后f(a)被认为不是全部函数,那么根本不会应用ADL。

Because the expression is not a function call, the argument-dependent name lookup ([basic.lookup.argdep]) does not apply and the friend function f is not found.



顺便说一句:在 namespace 范围内添加f的声明使函数名称f可见,并且f(a)将被视为函数调用(然后您会收到f返回void的错误,该错误不能用于初始化i)。例如
typedef int f;
namespace N {
  struct A;
  void f(A &);
  struct A {
    friend void f(A &);
    operator int();
    void g(A a) {
      int i = f(a);  // f is the friend function now
    }
  };
}

关于c++ - 有关使用好友功能查找姓名的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61378956/

相关文章:

c++ - 在 gcc 中意外调用了 const 重载。编译器错误或兼容性修复?

c++ - std::thread对象构造过程中的细节

C++类和静态

c++ - 无法编译以下代码以访问结构的变体

c++ - 通过结构化绑定(bind)从对/元组元素移动

c++ - 模板函数无法识别由 auto 变量引用的 lambda

c++ - constexpr 和未定义的行为

c++ - 将 unique_ptr 转换为 void* 并返回,我需要释放吗?

c++ - 从文本文件读取时使用 getline

c++ - 为什么或何时应该在调用前将可调用函数参数转换为右值?