扩展最初在内联命名空间的封闭命名空间中定义的内联命名空间中的命名空间

Extending a namespace in an inline namespace that initially was defined in the enclosing namespace of the inline namespace

我想检查一下自己是否正确理解了下面引自 C++ 20 标准的引述(英语不是我的母语)。

第 9.7.1 节命名空间定义:

2 In a named-namespace-definition, the identifier is the name of the namespace. If the identifier, when looked up (6.4.1), refers to a namespace-name (but not a namespace-alias) that was introduced in the namespace in which the named-namespace-definition appears or that was introduced in a member of the inline namespace set of that namespace, the namespace-definition extends the previously-declared namespace. Otherwise, the identifier is introduced as a namespace-name into the declarative region in which the named-namespacedefinition appears.

也就是说,命名空间可以在命名空间中定义,然后在其内联命名空间之一中扩展吗?或相反亦然。命名空间可以在内联命名空间中定义,然后在其封闭命名空间中扩展吗?

这是一个演示程序。

#include <iostream>

inline namespace N1
{
    inline namespace N2
    {
        namespace N3
        {
            void f( int ) { std::cout << "f( int )\n"; }
        }
    }

    namespace N3
    {
        void f( char ) { std::cout << "f( char )\n"; }
    }        
}

int main()
{
    N3::f( 10 );
    N3::f( 'A' );
}

程序输出为

f( int )
f( char )

但是对于这个程序,编译器会发出一个错误,指出对 'N3' 的引用不明确。

#include <iostream>

inline namespace N1
{
    namespace N3
    {
        void f( int ) { std::cout << "f( int )\n"; }
    }

    inline namespace N2
    {
        namespace N3
        {
            void f( char ) { std::cout << "f( char )\n"; }
        }        
    }
}

int main()
{
    N3::f( 10 );
    N3::f( 'A' );
}

我将尝试以不太密集(但可能不太精确)的方式重写标准措辞:

  1. 我们在命名空间 X.

  2. 我们遇到了类似 namespace Y { ... }.

  3. 的东西
  4. 我们查Y。如果 Y 不是命名空间名称,继续 1.

  5. Y 是在 X 中(直接)引入的吗?如果是,移至第 6 点。

  6. 是否在 X 的命名空间的内联集 2 的命名空间中引入了 Y?如果是,转到6。如果不是,继续1

  7. Y 确实扩展了我们在步骤 3 中找到的命名空间。

1 "Move on""ignore the cited standard paragraph" 的意义上.
2 The inline namespace set of N is the transitive closure of all inline namespaces in N.

may a namespace be defined in a namespace and then extended in one of its inline namespace?

没有。我们只考虑直接封闭的命名空间(N3 在第一个示例中的 N1 中扩展,在第二个示例中的 N2 中扩展)及其内联命名空间。这就是您的第二个示例不起作用的原因:N2(或其内联名称空间集)不包含 N3.

的任何先前定义

May a namespace be defined in an inline namespace and then be extended in its enclosing namespace?

是的。

您展示的示例与标准写法一致。

may a namespace be defined in a namespace and then extended in one of its inline namespace?

没有。在您的第二个示例中,当编译器在 N2 中看到 N3 的定义时,N3 的查找会找到在 N2 之外声明的 N3,但是N3 不是 "introduced in the namespace in which the named-namespace-definition appears"(因为它不在 N2 内),或者 "introduced in a member of the inline namespace set of that namespace" 因为 N2 的内联命名空间集是一组可传递的内联命名空间 里面 N2。因此,这个 N3 的新定义并没有扩展之前的定义。

May a namespace be defined in an inline namespace and then be extended in its enclosing namespace?

是的。在您的第一个示例中, N3 查找时发现 N2::N3 是 "introduced in a member of the inline namespace set" 因为 N2N1.[=35= 的内联命名空间集的一部分]

我们可以如下理解这种明显不对称的基本原理:在第二个示例中,当 N3 最初被定义时,它被定义为 N1 的成员不是 N1 的任何内联命名空间的成员。稍后,当 N2::N3 被定义时,如果要扩展 N1::N3,它将 追溯 使 N3 成为 [=11= 的成员],这违反常识,因此是不允许的。在第一个示例中,N3 最初被定义为内联命名空间 N2 的成员,稍后使用第二个定义扩展它没有问题。 (虽然我看不出这是有用的明显原因。)