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

问题描述 投票:7回答:2

我读了关于命名空间定义的部分。N3797的7.3.1条说。

inline关键字只有在扩展命名空间定义中使用过,才可以在该命名空间的原始命名空间定义中使用。

请看下面的代码片段。

namespace M
{
    int h;
}

inline namespace M
{
    int j = 6;
}

这段代码在编译成功后 -std=c++11 而没有这个选项。你能解释这种行为吗?它是一个 g++ bug?

c++ namespaces g++ inline
2个回答
5
投票

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

使用 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
          ^

所以这绝对是g++中的一个错误. 顺便说一下,它在这里被报告了。https:/gcc.gnu.orgbugzillashow_bug.cgi?id=53402。

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


0
投票
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 以便在扩展名空间块上明确这一意图。

© www.soinside.com 2019 - 2024. All rights reserved.