朋友定义函数的名称空间是什么?

时间:2018-07-19 22:35:50

标签: 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
    A::B::S::f(s); // not ok, no f in A::B::S
}

它甚至有一个名称空间吗? 拥有名称空间是否有意义?

如果我想消除常用习语中的通话歧义怎么办?

using std::swap;
swap(a, b);

我被迫在课外定义它并宣布为朋友吗?

3 个答案:

答案 0 :(得分:6)

朋友声明引用到最窄的封闭命名空间中的函数。但是,它不会将该函数的名称引入名称空间

  

9.3.1.2命名空间成员定义
   3 如果非本地类中的某个好友声明首先声明了一个类,函数,类模板或函数模板,则该好友是最里面的封闭名称空间的成员。朋友声明本身不是   对于不合格的查询或合格的查询可见的名称。

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

因此,在您的情况下,A::B::f是朋友。但是,名称fA::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::ff

此技术是我用来介绍运算符和其他自定义点的一种方法。它还允许在本身不是模板的模板类上创建每个模板的实例函数。

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

答案 2 :(得分:1)

是的,您可以在外部定义函数并使它成为特定类的朋友。它是绝对独立的功能,但是您允许它访问某些类。

首先在名称空间中声明的每个名称都是该名称空间的成员。如果非本地类中的某个朋友声明首先声明了一个类或函数,则该朋友类或函数是最内层的命名空间的成员。