C++ C++;17友元函数声明和内联命名空间

C++ C++;17友元函数声明和内联命名空间,c++,namespaces,language-lawyer,c++17,friend-function,C++,Namespaces,Language Lawyer,C++17,Friend Function,考虑以下程序 #include <iostream> namespace N1 { inline namespace N2 { class A { public: friend void f( const A & ); private: int x = 10; }; //void f( const A &

考虑以下程序

#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 );
}    
#包括
名称空间N1
{
内联命名空间N2
{
甲级
{
公众:
朋友空f(常数A&);
私人:
int x=10;
};
//无效f(常数A&);
}

空N2::f(常数A和A){std::cout正如我在评论中提到的那样,
f
的函数体和参数实际上并不相关,因为问题只是与
N2::f
的名称查找有关。删除它们之后,名称空间
N2
是否是
内联的也不重要。所有编译器在这两个方面的行为都是相同的案例

GCC发出警告,但在
N2::f
的定义上给出了一个带有
-迂腐错误的硬错误。MSVC和Clang总是在没有诊断的情况下接受代码

我认为您是对的,函数定义声明符中的
N2::f
应该通过限定名称查找规则进行查找,如果没有在
N2
的作用域中插入
f
声明,而不使用限定名称,则不应该查找
friend
声明

然而,似乎有人有意使这样一个名称空间外的定义格式良好

在公开的情况下,这个问题被重新提出,问题描述还得出结论,标准的规范性文本不允许定义。它还指出,正如您所观察到的,存在实施差异


对于Clang,有一个关于类似情况的bug报告。

它是如何隐形的?你清楚地定义了它,所以它是可见的。@ EuthoTIIB看到C++标准的引用。它说函数的定义在哪里变不可见?尽管N2::F在发布的代码中明确定义了吗?@ Eutho.Tiib一个。名称F在命名空间N2中是不可见的。那么,如果限定名称查找未找到函数,如何在封闭名称空间N1中定义函数?名称空间是内联的,这很重要,因为否则在演示程序中找不到限定名称A。@VladFrommosco是的,你是对的。我想我删除了函数体的内容,并且关键是编译器在
N2::f
的名称查找方面表现相同,无论名称空间是否内联。
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 & );
      |                         ^