C++ 为什么要内联未命名的名称空间?

C++ 为什么要内联未命名的名称空间?,c++,c++11,namespaces,inline-namespaces,C++,C++11,Namespaces,Inline Namespaces,对于大师来说,一个简单的例子是:C++11允许将未命名的名称空间声明为inline。这对我来说似乎是多余的;在未命名命名空间中声明的内容已被使用,就好像它们是在封闭的命名空间中声明的一样 所以我的问题是:这意味着什么 inline namespace /*anonymous*/ { // stuff } 它与传统有什么不同 namespace /*anonymous*/ { // stuff } 我们从C++98中了解并喜爱的?当使用inline时,有人能举例说明不同的行为吗

对于大师来说,一个简单的例子是:C++11允许将未命名的名称空间声明为
inline
。这对我来说似乎是多余的;在未命名命名空间中声明的内容已被使用,就好像它们是在封闭的命名空间中声明的一样

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

inline namespace /*anonymous*/ {
    // stuff
}
它与传统有什么不同

namespace /*anonymous*/ {
    // stuff
}
我们从C++98中了解并喜爱的?当使用
inline
时,有人能举例说明不同的行为吗

编辑:我只是想澄清一下,因为这个问题被标记为重复问题:一般来说,我不是在问命名内联名称空间。我理解那里的用例,我认为它们很棒。我特别想问的是,将未命名的命名空间声明为
inline
意味着什么。由于未命名的名称空间对于TU来说必须始终是本地的,所以rational的符号版本似乎不适用,所以我很好奇添加
inline
实际上做了什么


另一方面,关于未命名名称空间的标准[7.3.1.1]说:

inline
仅当它出现在未命名的命名空间定义中时才会出现

但在我的非语言律师眼中,这似乎是一个同义反复——“它出现在定义中,如果它出现在定义中”!对于加分,有人能解释一下标准语到底在说什么吗

编辑:Cubbi在评论中获得了加分:

该标准规定,未命名名称空间定义的行为就像被X替换一样,其中
inline
出现在X中,如果它出现在未命名名称空间定义中


以下是我发现的一个用途:

namespace widgets { inline namespace {

void foo();

} } // namespaces

void widgets::foo()
{
}
在本例中,
foo
具有内部链接,我们可以稍后使用
namespace::function
语法定义函数,以确保函数的签名正确。如果不使用
widgets
名称空间,那么
void foo()
定义将定义一个完全不同的函数。您也不需要重新打开名称空间以节省缩进级别


如果widgets
名称空间
中已经存在另一个名为
foo
的函数,那么这将给您带来一个模糊性,而不是严重的ODR违规。

我不知道是否已经完成了回答您自己问题的任务,但在满足了我的好奇心之后,所以我还是分享一下吧

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

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

template <> struct A<int> {};

如果没有
inline
,ADL将失败,我们必须显式地编写
NS::func(a)
。当然,如果我们在顶层定义了未命名的名称空间(通常是这样),那么无论它是否为内联名称空间,我们都无法获得ADL,但是…

可能与@Jeffrey重复,这是关于未命名的内联名称空间。@chris,我认为您可以混合使用未命名名称空间和内联名称空间的定义来给出答案。@Jeffrey这个问题是关于内联名称空间的,我理解。这个问题是专门问一个未命名的名称空间内联是什么意思,链接的答案(或我能找到的任何其他问题)似乎没有包括这个名称空间。好处很简单:标准规定,如果未命名命名空间定义出现在未命名命名空间定义中,
inline
出现在X中,那么未命名命名空间定义的行为就好像被X取代了一样。我不确定我是否理解您在这里做什么。为什么内部
内联命名空间
是必需的?@templatetypedef内部
内联命名空间
提供了
foo
内部链接。外部
名称空间
可以使用
名称空间::函数
语法对其进行定义,确保签名正确。啊,这很有意义。你可能想更新你的答案来明确指出这一点,因为我第一次没有提到这一点。酷,我喜欢这个!尽管如此,Clang似乎并没有这样做:“我得到的是‘foo’的越界定义与名称空间‘widgets’中的任何声明都不匹配”。不过,它与g++配合得很好,所以可能只是一个叮当作响的bug。@NirFriedman如果没有
inline
,您就无法定义
foo
函数而不再次打开未命名的命名空间。
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);
}