内联命名空间和扩展命名空间

inline namespace and extension namespace

本文关键字:命名空间 扩展      更新时间:2023-10-16

我阅读了关于名称空间定义的部分。N3797第7.3.1条规定:

内联关键字可用于扩展命名空间定义只有在原始名称空间定义之前使用过它时才会使用

考虑下面的代码片段:
namespace M
{
    int h;
}
inline namespace M
{
    int j = 6;
}

它在使用-std=c++11和不使用该选项时都编译成功。你能解释这种行为吗?是g++ bug吗?

你对标准的引用是明确的:这是不允许的。

使用clang++,我得到了非常明确的错误信息:

Test0614-1.cpp:17:18: error: non-inline namespace cannot be reopened as inline
inline namespace M
                 ^
Test0614-1.cpp:12:11: note: previous definition is here
namespace M
          ^

所以这肯定是c++中的一个bug。顺便说一下,报告在这里:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53402

编译器接受以前版本的标准的内联命名空间,而且至少没有警告,这似乎是一个问题。这在2010年已经被报告为bug,应该已经修复了:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43824

namespace M
{
    int h;
}
inline namespace M
{
    int j = 6;
}

这将导致错误'非内联命名空间不能作为内联命名空间打开'

你必须使用:

inline namespace M
{
    int h;
}
inline namespace M
{
    int j = 6;
}

反过来,你应该得到一个警告,你正在重新打开一个内联命名空间作为一个非内联命名空间

inline namespace M
{
    int h;
}
namespace M
{
    int j = 6;
}

但它并没有改变任何东西,从我可以告诉,所以我不知道为什么警告存在,但它存在的事实和::inline表明,否则。

namespace M
{
    inline namespace F {
        int h;
    }
}
namespace M::F {
    int k;
}

给出相同的警告,当使用:

时该警告将被抑制。
namespace M::inline F {
    int k;
}
有趣的是,这是非法的:
inline namespace M
{
    inline namespace F {
        int h;
    }
}
inline namespace M::inline F {
    int k;
}

您可以使用namespace M::inline Fnamespace M::F,但在这两种情况下您都会得到一个警告,即您正在将内联命名空间M打开为非内联命名空间。

::inline的存在可能只是为了抑制该警告,并使程序员从扩展名称空间中意识到它是一个内联名称空间,可以在没有作用域解析操作符的情况下访问,而不必检查主名称空间定义,这使得代码和意图清晰,并且因为大多数内联名称空间用于版本控制,它们总是嵌套在全局名称空间范围内的非内联名称空间中。不需要允许语法inline namespace M::inline F。以前必须使用namespace M {inline F {int k;}}而不是namespace M::F来明确扩展名称空间块的意图。