【问题标题】:Extending a namespace in an inline namespace that initially was defined in the enclosing namespace of the inline namespace在最初定义在内联命名空间的封闭命名空间中的内联命名空间中扩展命名空间
【发布时间】:2020-02-19 21:19:26
【问题描述】:

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

第 9.7.1 节命名空间定义:

2 在命名命名空间定义中,标识符是 命名空间。如果标识符在查找 (6.4.1) 时指的是 中引入的命名空间名称(但不是命名空间别名) 命名空间定义出现的命名空间或 在该命名空间的内联命名空间集合的成员中引入, 命名空间定义扩展了先前声明的命名空间。 否则,标识符将作为命名空间名称引入 出现命名空间定义的声明性区域。

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

这是一个演示程序。

#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' );
}

【问题讨论】:

    标签: c++ namespaces definition c++20


    【解决方案1】:

    可以在命名空间中定义命名空间,然后在其内联命名空间之一中扩展命名空间吗?

    没有。在您的第二个示例中,当编译器在N2 中看到N3 的定义时,N3 的查找会找到在N2 之外声明的N3,但N3 不是“在命名空间定义出现的命名空间”(因为它不在 N2 内),或“在该命名空间的内联命名空间集的成员中引入”,因为 N2 的内联命名空间集是传递的集合内联命名空间inside N2。因此,N3 的这个新定义不会扩展之前的定义。

    可以在内联命名空间中定义命名空间,然后在其封闭的命名空间中扩展命名空间吗?

    是的。在您的第一个示例中,N3 在查找时发现 N2::N3 是“在内联命名空间集的成员中引入的”,因为 N2N1 的内联命名空间集的一部分。

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

    【讨论】:

    【解决方案2】:

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

    1. 我们在命名空间X中的词汇。

    2. 我们遇到类似namespace Y { ... } 的内容。

    3. 我们查找Y。如果Y 不是命名空间名称,请继续1

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

    5. Y 是否被引入到属于 X 的命名空间的内联集2 的一部分的命名空间中?如果是,请移至 6。如果不是,请继续1

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

    1“忽略引用的标准段落”的意义上“继续”
    2The inline namespace set of N is the transitive closure of all inline namespaces in N.

    可以在命名空间中定义命名空间,然后在其内联命名空间之一中扩展命名空间吗?

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

    可以在内联命名空间中定义命名空间,然后在其封闭的命名空间中扩展命名空间吗?

    是的。

    您展示的示例与标准措辞一致。

    【讨论】:

    • 可以说更简单:内联命名空间集合的成员是封闭命名空间的成员。会不会?
    猜你喜欢
    • 1970-01-01
    • 2020-08-07
    • 2015-11-18
    • 1970-01-01
    • 2014-10-15
    • 1970-01-01
    • 1970-01-01
    • 2013-12-11
    • 1970-01-01
    相关资源
    最近更新 更多