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

9

我阅读了关于命名空间定义的部分。N3797的第7.3.1条款中说:

inline关键字只能用于扩展命名空间定义中,前提是它之前已经用于该命名空间的原始定义。

考虑以下代码片段:

namespace M
{
    int h;
}

inline namespace M
{
    int j = 6;
}

使用-std=c++11选项和不使用该选项都可以成功编译。你能解释一下这种行为吗?这是一个g++的bug吗?

2个回答

6
您对标准的参考是明确的:这是不允许的。
使用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++的一个bug。顺便提一下,这里有报告:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53402

编译器接受之前版本的内联命名空间而没有至少发出警告的事实似乎是一个问题。这在2010年已经被报告为错误并应该得到修复:https://gcc.gnu.org/bugzilla/show_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,以在扩展命名空间块上明确该意图。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接