C++ 友元定义函数的名称空间是什么?

C++ 友元定义函数的名称空间是什么?,c++,c++11,namespaces,overloading,friend-function,C++,C++11,Namespaces,Overloading,Friend Function,如果我在类中有一个定义为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

如果我在类中有一个定义为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);

我是否被迫在类之外定义它并将其声明为朋友?

是的,您在类之外定义函数并使其成为某个类的朋友。它是绝对独立的函数,但您允许它访问特定的类

在命名空间中首先声明的每个名称都是该命名空间的成员。如果非局部类中的友元声明首先声明了一个类或函数,则友元类或函数是最内部封闭命名空间的成员。

友元声明指的是来自最狭窄封闭命名空间的函数。但是,它不会将该函数的名称引入命名空间

9.3.1.2名称空间成员定义 3如果非本地类中的友元声明首先声明了类、函数、类模板或函数模板,则友元是最内层封闭命名空间的成员。朋友声明本身并不意味着 对非限定查找或限定查找可见的名称

因此,在您的情况下,
A::B::f
是一个朋友。但是,名称
f
A::B
中尚不存在。在
A::B
中提供
f
的明确声明之前,您将无法将其称为
A::B::f


名称查找能够通过一种称为(ADL)的特殊机制在非限定的
f(s)
调用中查找
f
。ADL是唯一可以“查看”您的函数的机制。

该函数位于
A::B
中,但只能通过ADL或Koenig查找找到

在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){}
模板
结构foo{
朋友无效不是一个模板(T){
};
模板
void是一个模板(T){

在与函数交朋友之前,您始终可以在某个名称空间中声明该函数。简单表达式
f(s)
之所以有效,是因为。该函数在
A::B::S
的范围内声明,但它不是该类的成员。@某个编程人员(ADL)不认为
f
A::B
中(与其参数的命名空间相同)?由于ADL的原因,不需要消除歧义。这就是这个习惯用法的全部要点:为了在查找中考虑
std::swap
(对于
std
)以外的类型,您必须将其放入本地范围。@一些程序员伙计:函数实际上在
A::B
中,而不是在
A::B::s
中。它只是普通名称查找不可见。@Walter它是
a::B
的成员,但由于
a::B::S
的词法范围之外没有
f
的声明,因此
f
只能通过非限定查找(并通过ADL查找)。@0x499602D2听起来像是一个答案。请把它贴出来。我相信@0x499602D2我相信@0x499602D2试着用更明智的方式说出我的想法。我不是以英语为母语的人,所以请原谅我的错误。C++具有块词法范围,因此必须在那里定义它。当您声明一个非限定的友元函数时,它会在最近的命名空间范围内命名一个函数。在以前未声明友元函数的情况下,声明在正常查找中不可见。对不起,我是新来的,还不能正确添加评论。如果有什么不可理解的,请让我知道,我会尽力更好地解释我的陈述和思考方式。术语“注入”不是“介绍”而是“注入”吗?@沃尔特:术语“注入”通常在发生某种名称注入时使用。在这种情况下,它不会发生。我想说,我们用哪个术语来表示没有发生的事情并不重要。)这很有趣,这意味着如果我定义这样的函数,它必须至少有一个封闭类型的参数。否则,将永远无法在名称空间之外找到它。还是陌生人。