如果我有一个函数定义为类中的friend。 该函数的命名空间是什么?
namespace A{namespace B{
struct S{
friend void f(S const&){};
};
}}
int main(){
A::B::S s{};
f(s); // ok
::f(s); // not ok, no f in global namespace
A::B::f(s); // no f in A::B
A::B::S::f(s); // not ok, no f in A::B::S
}
它甚至有一个名称空间吗? 拥有名称空间是否有意义?
如果我想消除常用习语中的通话歧义怎么办?
using std::swap;
swap(a, b);
我被迫在课外定义它并宣布为朋友吗?
答案 0 :(得分:6)
朋友声明引用到最窄的封闭命名空间中的函数。但是,它不会将该函数的名称引入名称空间
9.3.1.2命名空间成员定义
3 如果非本地类中的某个好友声明首先声明了一个类,函数,类模板或函数模板,则该好友是最里面的封闭名称空间的成员。朋友声明本身不是 对于不合格的查询或合格的查询可见的名称。
http://eel.is/c++draft/namespace.memdef#3
因此,在您的情况下,A::B::f
是朋友。但是,名称f
在A::B
中尚不存在。除非在A::B::f
中提供明确的f
声明,否则您将无法将其称为A::B
。
名称查找能够通过称为Argument Dependent Lookup(ADL)的特殊机制在不合格的f
呼叫中找到f(s)
。 ADL是唯一可以“看到”您的功能的机制。
答案 1 :(得分:3)
该函数位于A::B
中,但只能通过ADL或Koenig Lookup查找。
在main中对其进行命名的唯一方法是在类定义之外引入它。
是的,这很奇怪。
namespace A{namespace B{
inline void f(S const&);
struct S{
friend void f(S const&){};
};
}}
现在A::B::f
名f
。
此技术是我用来介绍运算符和其他自定义点的一种方法。它还允许在本身不是模板的模板类上创建每个模板的实例函数。
template<class T>
struct foo {
friend void not_a_template( T ){}
};
template<class T>
void is_a_template(T){}
答案 2 :(得分:1)
是的,您可以在外部定义函数并使它成为特定类的朋友。它是绝对独立的功能,但是您允许它访问某些类。
首先在名称空间中声明的每个名称都是该名称空间的成员。如果非本地类中的某个朋友声明首先声明了一个类或函数,则该朋友类或函数是最内层的命名空间的成员。