为什么我们不能在本地类中定义友元函数? 我有一个C++的下面代码片段。在main()函数中声明了一个类

为什么我们不能在本地类中定义友元函数? 我有一个C++的下面代码片段。在main()函数中声明了一个类,c++,c++11,friend,local-class,C++,C++11,Friend,Local Class,为什么我们不能在本地类中定义友元函数 #include<iostream> int main() { class Foo { void foo() {} // Ok friend void Bar(){}; // Error }; } #包括 int main() { 福班 { void foo(){}//Ok 友元无效条(){};//错误 }; } 因为本地类的成员函数必须完全在类主体内部定义,而友元函数不是成员函数。我们

为什么我们不能在本地类中定义友元函数

#include<iostream>

int main()
{
    class Foo
    {
        void foo() {} // Ok
        friend void Bar(){}; // Error
    };
}
#包括
int main()
{
福班
{
void foo(){}//Ok
友元无效条(){};//错误
};
}

因为本地类的成员函数必须完全在类主体内部定义,而友元函数不是成员函数。我们在类内声明了友元函数,在类外定义了友元函数

根据:

本地课程

  • 本地类不能有静态成员
  • 局部类的成员函数没有链接
  • 局部类的成员函数必须完全在类体内定义
  • 闭包类型以外的本地类(因为C++14)不能有成员模板
  • 本地类不能有好友模板
  • 本地类无法在类定义中定义友元函数
  • 函数(包括成员函数)中的本地类可以访问封闭函数可以访问的相同名称。

这是一个实际的原因。首先也是最重要的是,内联好友定义不能通过限定或非限定查找找到。它只能由ADL找到。因此,如果我们从您的示例中获取类,将其放在全局范围内,并尝试调用
Bar

class Foo
{
    friend void Bar(){};
    void foo() {
      Bar();
    }
};

我们将被通知,
Bar
未在该范围内声明。所以如果是在一个本地班级。你不能从会员那里打电话。不能在函数内部调用它。你可以称之为篮球的唯一方式是一些篮球或日常生活能力。所以语言就是不允许这样。这被认为不是一个有用的功能。

没有令人信服的技术理由。你说ADL找不到它?嗯,这基本上是问题的一部分:为什么ADL找不到它?只要扩展ADL,让它找到它

这种限制的一个设计级原因可能是源于友元声明中对非限定名称的语言处理

在本地类的友元声明中使用的非限定名称指的是最近封闭的非类作用域中的名称。这种对非限定名称的处理非常重要,因为这是本地类相互引用的唯一方式(因为很明显,本地类没有限定名称)

此规则也适用于具有非限定名称的友元函数声明。C++没有本地函数,但是这样的朋友声明仍然可以引用函数的局部非定义声明(完全合法)< /P> 现在,如果在本地类中定义友元函数(当然是使用非限定名称),您会提出什么建议?这种声明引入了什么功能?具体到什么范围?根据定义,它不是类的成员,因为友元声明不引入类成员。它不能是最近的封闭局部范围的成员,因为这将使它成为本地函数,C++不支持本地函数。 我们不能仅仅统一地改变友元声明中所有非限定名称的行为,并说它们现在应该引用最近的封闭命名空间范围中的名称,因为这样就无法引用本地类(如上所示)

解决这种情况的唯一方法是仅使类内友元函数定义引用(并定义)最近封闭命名空间范围中的函数。这样的函数只能通过[modified]ADL调用(假设我们对此没有意见)。但这意味着我们必须对友元函数定义中的非限定名称给予不同的处理(与非定义友元声明相反)。这将是相当不雅和混乱的。因此,语言作者决定反对它

请注意,在C++14之后,这一点的重要性可能会显著增加,它为我们提供了函数中的
auto
返回类型。从那以后,当地的班级甚至不再像过去那样“当地化”

auto foo() 
{
  struct S // Local class
  {
    void bar() {}
  };

  return S();
}

int main() 
{
  auto a = foo();
  a.bar(); // An object of local class used outside of its original scope

  typedef decltype(a) S; // Local type is "stolen" from its original scope
  S b;                   // and used to freely declare objects in a completely
  b.bar();               // different scope 
}

我看不出这个答案是如何成为“理由”的。基本上,这只是重申了这个问题。
void foo() {}

int main()
{
  void foo(); // refers to `::foo`

  class A {
    friend void foo(); // refers to local `foo`, which is `::foo`
  };
}
auto foo() 
{
  struct S // Local class
  {
    void bar() {}
  };

  return S();
}

int main() 
{
  auto a = foo();
  a.bar(); // An object of local class used outside of its original scope

  typedef decltype(a) S; // Local type is "stolen" from its original scope
  S b;                   // and used to freely declare objects in a completely
  b.bar();               // different scope 
}