【问题标题】:C++ 17 friend function declaration and inline namespaceC++ 17 友元函数声明和内联命名空间
【发布时间】:2020-04-10 11:35:03
【问题描述】:

考虑以下程序

#include <iostream>

namespace N1
{
    inline namespace N2
    {
        class A
        {
        public:
            friend void f( const A & );
        private:
            int x = 10;
        };

        //void f( const A & );
    }

    void N2::f( const A &a ) { std::cout << a.x << '\n'; }
}

int main()
{
    using namespace N1;

    A a;

    f( a );
}    

根据 C++ 17 标准(10.3.1.2 命名空间成员定义)

3 如果非本地类中的友元声明首先声明了一个类, 函数、类模板或函数模板97 朋友是成员 最里面的封闭命名空间。朋友声明不 本身使名称对非限定查找(6.4.1)可见或 合格的查找 (6.4.3)。

所以友元函数的名称在命名空间 N2 中是不可见的。所以它在命名空间 N1 中也应该是不可见的。

但是,clang HEAD 10.0.0 编译和执行代码时不会发出警告。

编译器gcc HEAD 10.0.0 20191发出警告

prog.cc:18:10: warning: 'void N1::N2::f(const N1::N2::A&)' has not been declared within 'N1::N2'
   18 |     void N2::f( const A &a ) { std::cout << a.x << '\n'; }
      |          ^~
prog.cc:10:25: note: only here as a 'friend'
   10 |             friend void f( const A & );
      |                         ^

但是运行程序并输出正确的结果。

Visual C++ 2019 也成功编译了代码,没有警告,程序输出了预期的结果。

是否存在三个编译器的错误,因为名称 f 是不可见的,所以封闭命名空间中友元函数 f 的定义不正确?

【问题讨论】:

  • 它是如何隐形的?你清楚地定义了它,所以它是可见的。
  • @ÖöTiib 请参阅 C++ 标准的引用。
  • 哪里说函数的定义不可见了?
  • 尽管 N2::f 已在发布的代码中明确定义?
  • @ÖöTiib 还有一个。名称 f 在命名空间 N2 中是不可见的。那么如果限定名查找找不到函数,如何在封闭的命名空间 N1 中定义函数呢?

标签: c++ namespaces language-lawyer c++17 friend-function


【解决方案1】:

正如我在评论中提到的,f 的函数体和参数并不真正相关,因为问题仅与 N2::f 的名称查找有关。删除它们后,命名空间N2 是否为inline 也无关紧要。在这两种情况下,所有编译器的行为方式都相同。

GCC 发出警告,但在N2::f 的定义上给出了-pedantic-errors 的硬错误。 MSVC 和 Clang 总是接受没有诊断的代码。

我认为你是对的,函数定义声明器中的措辞 N2::f 应该通过限定名称查找规则进行查找,如果没有 f 的干预声明,它不应该找到 friend 声明N2 的作用域,不使用限定名。

但是,defect report 1477 似乎有意使这种名称空间外的定义格式正确。

在公开的CWG issue 1900 中提出了这个问题,并且问题描述还得出结论,标准的规范性文本不允许定义。正如您所观察到的,它还指出存在实现差异。

对于 Clang,有一个关于类似案例 here 的错误报告。

【讨论】:

  • 内联命名空间很重要,否则在演示程序中将找不到非限定名称 A。
  • @VladfromMoscow 是的,你是对的。我想我删除了函数体和参数的内容并忘记了它。关键是编译器在N2::f 的名称查找方面的行为是相同的,无论命名空间是否是内联的。
猜你喜欢
  • 2013-05-19
  • 2016-12-12
  • 1970-01-01
  • 2012-06-11
  • 2012-06-11
  • 1970-01-01
  • 2011-06-14
  • 2015-01-30
  • 2012-12-18
相关资源
最近更新 更多