首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++ 17好友函数声明和内联命名空间

C++ 17好友函数声明和内联命名空间
EN

Stack Overflow用户
提问于 2019-12-17 22:43:10
回答 1查看 224关注 0票数 1

考虑以下程序

代码语言:javascript
复制
#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如果非本地类中的朋友声明首先声明一个类、函数、类模板或函数template97,则朋友是最内部封闭名称空间的成员。朋友声明本身不会使名称对非限定查找(6.4.1)或限定查找(6.4.3)可见。

因此,朋友函数的名称在命名空间N2中是不可见的。因此,它也应该在命名空间N1中不可见。

但是,代码是在没有警告的情况下由clangHead10.0.0编译和执行的。

编译器gcc头10.0.0 20191发出警告

代码语言:javascript
复制
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也成功地编译了代码,没有警告,程序输出预期的结果。

这三个编译器是否有bug,因为名称f是不可见的,所以封闭名称空间中的朋友函数f的定义是不正确的?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-12-17 23:30:12

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

GCC警告说,但是-pedantic-errorsN2::f的定义上犯了很大的错误。MSVC和Clang总是接受没有诊断的代码。

我认为您是对的,按照函数定义声明器中的N2::f的措辞,应该使用限定名查找规则来查找,如果在N2的作用域上没有f的中间声明,就不应该使用限定名来查找N2声明。

然而,有一个缺陷报告1477,它似乎有意图使这样一个命名空间外的定义格式良好。

在开放的中央工作组第1900期中,提出了这个问题,问题的描述也得出结论,标准的规范文本不允许定义。它还注意到,正如您所观察到的,存在实现差异。

对于Clang,有一个关于类似案例这里的bug报告。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59383156

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档