我已经阅读了[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/