namespace
1 语法
namespace 命名空间名 { 声明序列 } (1)
inline namespace 命名空间名 { 声明序列 } (2) (C++11 起)
namespace { 声明序列 } (3)
命名空间名 :: 成员名 (4)
using namespace 命名空间名 ; (5)
using 命名空间名 :: 成员名 ; (6)
namespace 名字 = 有限定命名空间 ; (7)
namespace 命名空间名 :: 成员名 { 声明序列 } (8) (C++17 起)
namespace 命名空间名::inline 成员名 { 声明序列 } (9) (C++20 起)
- \1) 命名空间 命名空间名 的具名命名空间定义。
- \2) 命名空间 命名空间名 的内联命名空间定义。命名空间名 内的声明将在它的外围命名空间可见。
- \3) 无名命名空间定义。它的成员具有从声明点到翻译单元结尾的潜在作用域,并具有内部链接。
- \4) 命名空间名(还有类名)可以出现在作用域解析运算符的左侧,作为有限定的名字查找的一部分。
- \5) using 指令:从 using 指令之后到指令出现的作用域结尾为止,以对任何名字的无限定名字查找的视点来说,来自 命名空间名 的任何名字均可见,如同它在同时含有该 using 指令和 命名空间名 两者的最接近外围命名空间作用域声明一样。
- \6) using 声明:令来自命名空间 命名空间名 的符号 成员名 对无限定名字查找可见,如同将它在包含该 using 声明的相同的类作用域、块作用域或命名空间之中声明一样。
- \7) 命名空间别名定义(namespace-alias-definition):令 名字 成为另一命名空间的同义词:见命名空间别名。
- \8) 嵌套命名空间定义:namespace A::B:: C { ... }
等价于 namespace A { namespace B { namespace C { ... } } }
。
- \9) 嵌套内联命名空间定义:namespace A::B::inline C { ... }
等价于 namespace A::B { inline namespace C { ... } }
。inline 可以在首个以外的每个命名空间名之前出现:namespace A::inline B::C {}
等价于 namespace A { inline namespace B { namespace C {} } }
。
2 inline 命名空间
- 支持时间:C++11
内联命名空间能够把空间内函数和类型导出到父命名空间中,这样即使不指定子命名空间也可以使用其空间内的函数和类型了,比如:
#include <iostream>
namespace Parent {
namespace Child1
{
void foo() { std::cout << "Child1::foo()" << std::endl; }
}
inline namespace Child2
{
void foo() { std::cout << "Child2::foo()" << std::endl; }
}
}
int main()
{
Parent::Child1::foo();
Parent::foo();
}
3 嵌套命名空间
- 支持时间:C++17
有时候打开一个嵌套命名空间可能只是为了向前声明某个类或者函数,但是却需要编写冗长的嵌套代码,加入一些无谓的缩进,这很难让人接受。C++17 标准允许使用一种更简洁的形式描述嵌套命名空间,例如:
namespace A::B::C {
int foo() { return 5; }
}
等价于
namespace A {
namespace B {
namespace C {
int foo() { return 5; }
}
}
}
4 嵌套 inline 命名空间
- 支持时间:C++20
在 C++17 标准中没有办法简洁地定义内联命名空间,这个问题直到 C++20 标准才得以解决。在 C++20 中,我们可以这样定义内联命名空间:
namespace A::B::inline C {
int foo() { return 5; }
}
// 或者
namespace A::inline B::C {
int foo() { return 5; }
}
等价于
namespace A::B {
inline namespace C {
int foo() { return 5; }
}
}
namespace A {
inline namespace B {
namespace C {
int foo() { return 5; }
}
}
}