什么是在一个类中定义的朋友函数的完全限定名?
什么是在一个类中定义的朋友函数的完全限定名?
我最近看到一个类似于以下的例子。 什么是val()
的完全限定名?
#include <iostream> namespace foo { class A { int x; public: A(int x = 0) : x(x) { } friend int val(const A &a) { return ax; } }; } int main() { foo::A a(42); // val() found using ADL: std::cout << val(a) << std::endl; // foo::val(a); // error: 'val' is not a member of 'foo' // foo::A::val(a); // error: 'val' is not a member of 'foo::A' return 0; }
依赖于参数的查找是唯一可以findval()
方法吗?
诚然,这不是源于实际问题。 我只是想要获得更好的理解。
依赖于参数的查找是唯一可以findval()的方法吗?
是的,这是唯一的方法。 引用[namespace.memdef] / 3中的圣洁标准:
如果非本地类中的朋友声明首先声明一个类,函数,类模板或函数模板,则该朋友是最内层的名字空间的成员。 这个朋友声明本身并不会使得这个名字对于不合格的查找或合格的查找是可见的。
所以虽然val
是foo
的成员,但是仅从朋友声明中查找是不可见的。 需要使用类外定义(也是声明)来使其可见。 对于内联定义(并且没有类外声明),这意味着ADL是调用该函数的唯一方法。
作为一个额外的好处,C ++曾经有一个“朋友名注入”的概念。 然而,这已被删除,ADL的规则调整为替代。 更详细的概述可以在WG21论文N0777 (pdf)中find。
C ++标准[7.3.1.2/3(ISO / IEC 14882:2011)]:
名称空间中首先声明的每个名称都是该名称空间的成员。 如果非本地类中的朋友声明首先声明了一个类或函数,则该朋友类或函数是最内层的名字空间的成员。 直到在该命名空间范围内(在授予友谊的类定义之前或之后)提供匹配声明之前,通过无限制查找(3.4.1)或合格查找(3.4.3)才能find该朋友的名字 。 如果调用好友函数,则可以通过名称查找find其名称,该名称查找考虑了与函数参数types(3.4.2)相关的名称空间和类的函数。 如果朋友声明中的名称既不是限定名也不是模板标识,并且声明是函数或详细types说明符,则确定实体是否先前已声明的查找不应考虑最内层封闭名称空间之外的任何作用域 。