那么内联未命名的命名空间?

Tri*_*dle 20 c++ namespaces c++11 inline-namespaces

对于大师来说很快:C++ 11允许声明未命名的命名空间inline.这对我来说似乎是多余的; 在未命名的命名空间中声明的事物已经被使用,好像它们是在封闭的命名空间中声明的一样.

所以我的问题是:这是什么意思

inline namespace /*anonymous*/ {
    // stuff
}
Run Code Online (Sandbox Code Playgroud)

它与传统的有什么不同?

namespace /*anonymous*/ {
    // stuff
}
Run Code Online (Sandbox Code Playgroud)

我们从C++ 98中了解和喜爱?使用时,有人能举出不同行为的例子inline吗?

编辑:只是为了澄清,因为这个问题被标记为重复:我一般不会询问命名内联命名空间.我理解那里的用例,我认为它们很棒.我特别询问将命名的命名空间声明为什么意思inline.由于未命名的命名空间必然始终是TU的本地命名空间,因此符号版本化似乎并不适用,所以我很好奇添加inline实际上了什么.


另外,关于未命名的命名空间的标准[7.3.1.1]说:

inline当且仅当它出现在unnamed-namespace-definition中时才会出现

但这对我的非语言律师的眼睛来说似乎是一种重言式 - "它出现在定义中,如果它出现在定义中"!对于奖励积分,任何人都可以解释一下这些标准实际上在说什么吗?

编辑: Cubbi在评论中声称奖励积分:

该标准是说,不具名的命名空间定义的行为就好像它被取代X,其中inline出现在X当且仅当它出现在未命名的命名空间定义

Tri*_*dle 10

我不知道在SO上回答你自己的问题是否已经完成了,但是在我的好奇心得到满足之后,我也可以分享它.

内联命名空间的定义不仅包括将名称提升到封闭命名空间(无论如何都会为未命名的命名空间发生),还允许在内联命名空间内定义的模板在其外部进行专门化.事实证明,这也适用于未命名的命名空间:

inline // comment this out to change behaviour
namespace { 
    template <typename T> struct A {};
}

template <> struct A<int> {};
Run Code Online (Sandbox Code Playgroud)

没有inline,g ++抱怨尝试从不同的命名空间专门化模板(虽然Clang没有).有了inline,它编译得很好.对于这两个编译器,在专门化中定义的任何内容仍然标记为具有内部链接(根据nm),就像它在未命名的命名空间内一样,但我想这是可以预期的.我真的没有想到为什么这会有用,但我们走了.

可以说更有用的效果来自内联命名空间的依赖参数的查找的更改,这也会影响未命名的内联命名空间.考虑以下情况:

namespace NS {
    // Pretend this is defined in some header file
    template <typename T>
    void func(const T&) {}

    // Some type definition private to this TU
    inline namespace {
        struct A {};
    }

} // end namespace NS

int main()
{
    NS::A a;
    func(a);
}
Run Code Online (Sandbox Code Playgroud)

没有inline,ADL失败,我们必须明确写NS::func(a).当然,如果我们在顶层定义了未命名的命名空间(通常会这样),那么我们不会得到ADL是否是内联的,但仍然......


Sim*_*ple 8

这是我发现的一个用途:

namespace widgets { inline namespace {

void foo();

} } // namespaces

void widgets::foo()
{
}
Run Code Online (Sandbox Code Playgroud)

在这个例子中,foo有内部链接,我们可以稍后使用namespace::function语法定义函数,以确保函数的签名是正确的.如果您不使用widgets命名空间,则void foo()定义将定义完全不同的函数.您也无需重新打开命名空间,从而节省了一定程度的缩进.

如果已经foo在小部件中调用了另一个函数,namespace那么这将给你一个歧义,而不是一个讨厌的ODR违规.

  • @NirFriedman没有`inline`你不能再定义`foo`函数而不再打开未命名的命名空间. (2认同)