有关使用好友功能查找姓名的问题 [英] A question about name lookup with friend function

查看:65
本文介绍了有关使用好友功能查找姓名的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have read the standard section of [basic.lookup.unqual] and I am confused about this:

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&).如果在那里找不到名称,它将在外部名称空间中执行查找.显然,在类 A 中有一个名称 void f(A&),正如标准所说:

Please consider the above code; I don't understand why name f is type int, instead of void f(A &). In my understanding, the name lookup should find void f(A &) firstly in class scope A. If no name can be found there, it would perform a lookup in outside namespace. Obviously, there is a name void f(A &) in class A and as the standard says:

找到名称声明后立即结束查找

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

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

So why does the name refer to type int here, if there are other particular rules about these?

推荐答案

首先,朋友声明本身不会使 f 对于名称查找可见, f 只能由ADL找到.

Firstly, the friend declaration itself doesn't make f visible for name lookup, f could only be found by ADL.

在类或类模板X的朋友声明中首先声明的名称成为X的最内层命名空间的成员,但对于查找(除了考虑X的依赖于参数的查找除外)不可见,除非在提供了命名空间范围

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

friend声明本身不会使名称对不合格的查询或合格的查询可见.[注意:如果在名称空间范围内(在授予友谊的类定义之前或之后)提供了匹配的声明,则朋友的名称将在其名称空间中可见.—注释[end note]如果调用了朋友函数或函数模板,则可以通过名称查找来找到其名称,该名称查找将考虑来自与函数参数类型([basic.lookup.argdep])相关联的名称空间和类中的函数.如果朋友声明中的名称既不是合格的也不是模板ID,并且声明是函数或精化类型说明符,则用于确定该实体先前是否已声明的查找将不考虑最内层的封闭命名空间之外的任何范围.

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)是否为函数调用.

The problem is for ADL to be applied, whether f(a) is a function call must be determined in advance.

[basic.lookup.unqual]/3

(重点是我的)

在[basic.lookup.argdep]中描述了对用作函数调用的后缀表达式的不合格名称的查找.[注意:出于确定(在解析过程中)表达式是否为函数调用的后缀表达式的目的,通常使用名称查找规则.

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

In this stage, the function name f is invisible and the typename f is found, then f(a) is considered not to be a function all, then ADL won't be applied at all.

因为表达式不是函数调用,所以不应用依赖于参数的名称查找([basic.lookup.argdep]),也找不到朋友函数f.

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.

BTW:在命名空间范围内添加 f 的声明使函数名称 f 可见,而 f(a)将被视为函数调用(然后您会得到 f 返回 void 的错误,该错误不能用于初始化 i ).例如

BTW: Adding the declaration of f at namespace scope makes the function name f visible and f(a) would be considered as function call (and then you'll get the error that f returns void which can't be used to initialize i). e.g.

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
    }
  };
}

这篇关于有关使用好友功能查找姓名的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆