友元定义函数的命名空间是什么?

What is the namespace of a friend-defined function?

如果我在 class 中定义了一个 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);

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

是的,你在外面定义了一个函数,让它成为某个class的友元。它是绝对独立的函数,但你允许它访问某些class。

在命名空间中首次声明的每个名称都是该命名空间的成员。如果非本地 class 中的友元声明首先声明一个 class 或函数,则友元 class 或函数是最内层封闭命名空间的成员。

友元声明引用来自最窄封闭命名空间的函数。但是,它没有将那个函数的名称引入到命名空间

9.3.1.2 Namespace member definitions
3 If a friend declaration in a non-local class first declares a class, function, class template or function template the friend is a member of the innermost enclosing namespace. The friend declaration does not by itself make the name visible to unqualified lookup or qualified lookup.

http://eel.is/c++draft/namespace.memdef#3

所以,在你的情况下 A::B::f 是朋友。但是,名称 f 还不存在于 A::B 中。在 A::B.

中明确声明 f 之前,您将无法将其称为 A::B::f

名称查找能够通过称为 Argument Dependent Lookup (ADL) 的特殊机制在不合格的 f(s) 调用中找到 f。 ADL 是唯一可以 "see" 您的功能的机制。

该函数在 A::B 中,但只能通过 ADL 或 Koenig Lookup 找到。

它在 main 中命名的唯一方法是在 class 定义之外引入它。

是的,这很奇怪。

namespace A{namespace B{
  inline void f(S const&);
  struct S{
    friend void f(S const&){};
  };
}}

现在 A::B::f 命名 f

这个技巧是我用来介绍运算符和其他自定义点的东西。它还允许在本身不是模板的模板 classes 上创建每个模板实例函数。

template<class T>
struct foo {
  friend void not_a_template( T ){}
};
template<class T>
void is_a_template(T){}