c++ - 为什么内联未命名的命名空间?

标签 c++ c++11 namespaces inline-namespaces

给专家的快速提示:C++11 允许将未命名的命名空间声明为 inline。这对我来说似乎是多余的;在未命名的命名空间中声明的东西已经被使用,就好像它们是在封闭的命名空间中声明的一样。

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

inline namespace /*anonymous*/ {
    // stuff
}

和传统的有什么不同

namespace /*anonymous*/ {
    // stuff
}

我们从 C++98 开始了解和喜爱?谁能举例说明使用 inline 时的不同行为?

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


顺便说一句,关于未命名命名空间的标准 [7.3.1.1] 说:

inline appears if and only if it appears in the unnamed-namespace-definition

但在我的非语言律师眼中,这似乎是一个重言式——“它出现在定义中,当且仅当它出现在定义中”!对于加分,谁能解释一下这句标准话到底在说什么?

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

the standard is saying that unnamed-namespace-definition behaves as if it were replaced by X where inline appears in X iff it appears in the unnamed-namespace-definition

最佳答案

我不知道在SO上回答你自己的问题是否已经完成,但是在玩了一些之后我的好奇心得到了满足,所以我不妨分享一下。

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

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

template <> struct A<int> {};

如果没有 inline,g++ 会提示试图从不同的命名空间特化模板(尽管 Clang 不会)。使用 inline,它编译得很好。对于这两个编译器,在特化中定义的任何东西仍然被标记为具有 internal links(根据 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);
}

如果没有 inline,ADL 会失败,我们必须显式编写 NS::func(a)。当然,如果我们在顶层定义了未命名的命名空间(就像通常那样),那么无论它是否是内联的,我们都不会得到 ADL,但仍然......

关于c++ - 为什么内联未命名的命名空间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20208591/

相关文章:

c++ - 在 C++ 中比较 std::string 与常量与比较 char 数组与常量

c++ - 在 cpack 输出中包含外部库

c++ - vector C++ 调整大小

c++ - std::find 有两种不同的类型

c++ - 头文件和命名空间有什么区别?

c++ - 如何重新设计 C++ 类?

C++11 - 区分右值指针

c# - 在不影响客户端的情况下更改 WCF 项目的命名空间

php - 从 PHP 命名空间中定义全局函数

c++ - 断开连接后重新连接 boost beast (asio) websocket 和 http 连接时出错