C++11 允许 inline namespace
,其所有成员也自动位于封闭的 namespace
中。我想不出任何有用的应用程序——有人可以给出一个简短的例子来说明需要 inline namespace
以及它是最惯用的解决方案的情况吗?
(另外,我不清楚当 namespace
被声明为 inline
时会发生什么,但不是所有声明,它们可能存在于不同的文件中。是'这不是自找麻烦吗?)
内联命名空间是类似于 symbol versioning 的库版本控制功能,但纯粹在 C++11 级别(即跨平台)实现,而不是作为特定二进制可执行格式的功能(即特定于平台)。
这是一种机制,库作者可以通过该机制使嵌套命名空间看起来并像其所有声明都在周围的命名空间中一样(内联命名空间可以嵌套,因此“更多嵌套”的名称一直渗透到第一个非内联命名空间,并且看起来和行为就好像它们的声明也在两者之间的任何命名空间中一样)。
以 vector
的 STL 实现为例。 .如果我们从 C++ 开始就有内联命名空间,那么在 C++98 中,标题 <vector>
可能看起来像这样:
namespace std {
#if __cplusplus < 1997L // pre-standard C++
inline
#endif
namespace pre_cxx_1997 {
template <class T> __vector_impl; // implementation class
template <class T> // e.g. w/o allocator argument
class vector : __vector_impl<T> { // private inheritance
// ...
};
}
#if __cplusplus >= 1997L // C++98/03 or later
// (ifdef'ed out b/c it probably uses new language
// features that a pre-C++98 compiler would choke on)
# if __cplusplus == 1997L // C++98/03
inline
# endif
namespace cxx_1997 {
// std::vector now has an allocator argument
template <class T, class Alloc=std::allocator<T> >
class vector : pre_cxx_1997::__vector_impl<T> { // the old impl is still good
// ...
};
// and vector<bool> is special:
template <class Alloc=std::allocator<bool> >
class vector<bool> {
// ...
};
};
#endif // C++98/03 or later
} // namespace std
取决于 __cplusplus
的值, 一个或另一个 vector
选择实现。如果您的代码库是用 C++98 之前的版本编写的,并且您发现 vector
的 C++98 版本当您升级编译器时给您带来麻烦,“所有”您要做的就是找到对 std::vector
的引用在您的代码库中并将它们替换为 std::pre_cxx_1997::vector
.
下一个标准来了,STL 供应商只是再次重复这个过程,为 std::vector
引入一个新的命名空间。与 emplace_back
支持(需要 C++11)并内联那个 iff __cplusplus == 201103L
.
好的,那我为什么需要一个新的语言功能呢?我已经可以执行以下操作以达到相同的效果,不是吗?
namespace std {
namespace pre_cxx_1997 {
// ...
}
#if __cplusplus < 1997L // pre-standard C++
using namespace pre_cxx_1997;
#endif
#if __cplusplus >= 1997L // C++98/03 or later
// (ifdef'ed out b/c it probably uses new language
// features that a pre-C++98 compiler would choke on)
namespace cxx_1997 {
// ...
};
# if __cplusplus == 1997L // C++98/03
using namespace cxx_1997;
# endif
#endif // C++98/03 or later
} // namespace std
取决于 __cplusplus
的值,我得到了其中一个实现。
你几乎是正确的。
考虑以下有效的 C++98 用户代码(在 C++98 中已经允许完全特化位于命名空间 std
中的模板):
// I don't trust my STL vendor to do this optimisation, so force these
// specializations myself:
namespace std {
template <>
class vector<MyType> : my_special_vector<MyType> {
// ...
};
template <>
class vector<MyOtherType> : my_special_vector<MyOtherType> {
// ...
};
// ...etc...
} // namespace std
这是完全有效的代码,其中用户为一组类型提供自己的 vector 实现,而她显然知道比在 STL(她的拷贝)中找到的更有效的实现。
但是:当特化一个模板时,你需要在它被声明的命名空间中这样做。标准说 vector
在命名空间 std
中声明,所以这是用户理所当然希望专门化该类型的地方。
此代码适用于非版本化命名空间 std
,或使用 C++11 内联命名空间功能,但不使用使用 using namespace <nested>
的版本控制技巧,因为这暴露了 vector
所在的真正命名空间的实现细节。定义不是 std
直接。
您可以通过其他漏洞检测嵌套命名空间(请参阅下面的注释),但内联命名空间会将它们全部塞住。这就是它的全部。对 future 非常有用,但 AFAIK 标准并没有为它自己的标准库规定内联命名空间名称(不过我很想被证明是错误的),所以它只能用于第三方库,而不是标准本身(除非编译器供应商同意命名方案)。
我是一名优秀的程序员,十分优秀!