内联名称空间是类似于symbol versioning的库版本控制功能,但纯粹在C 11级(即跨平台)实现,而不是特定二进制可执行格式(即特定于平台)的功能 .
它是一种机制,通过该机制,库作者可以使嵌套的命名空间看起来并且就好像它的所有声明都在周围的命名空间中一样(内联命名空间可以嵌套,因此“更多嵌套”的名称一直渗透到第一个非命名空间-inline命名空间,看起来和行为就好像它们的声明也在它们之间的任何命名空间中) .
例如,考虑 vector 的STL实现 . 如果我们从C的开头有内联命名空间,那么在C 98中, Headers 可能看起来像这样:
namespace std {
#if __cplusplus < 1997L // pre-standard C++
inline
#endif
namespace pre_cxx_1997 {
template __vector_impl; // implementation class
template // e.g. w/o allocator argument
class vector : __vector_impl { // 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 vector : pre_cxx_1997::__vector_impl { // the old impl is still good
// ...
};
// and vector is special:
template >
class vector {
// ...
};
};
#endif // C++98/03 or later
} // namespace std
根据 __cplusplus 的值,选择一个或另一个 vector 实现 . 如果您的代码库是在C-98之前编写的,并且您发现在升级编译器时C28版本的 vector 会给您带来麻烦,那么您需要做的是在代码库中找到对 std::vector 的引用并替换他们是 std::pre_cxx_1997::vector .
进入下一个标准,STL供应商再次重复该过程,为 std::vector 引入一个新的命名空间,支持 emplace_back (需要C11)并内联一个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用户代码(允许完全专门化C98中名称空间 std 中的模板):
// I don't trust my STL vendor to do this optimisation, so force these
// specializations myself:
namespace std {
template <>
class vector : my_special_vector {
// ...
};
template <>
class vector : my_special_vector {
// ...
};
// ...etc...
} // namespace std
这是完全有效的代码,其中用户为一组类型提供其自己的向量实现,其中她显然知道比在STL(她的副本)中找到的更有效的实现 .
但是:在专门化模板时,您需要在声明它的名称空间中执行此操作 . 标准说 vector 在名称空间 std 中声明,因此用户正确期望专门化该类型 .
此代码适用于非版本化命名空间 std ,或使用C 11内联命名空间功能,但不适用于使用 using namespace 的版本控制技巧,因为这会公开实现详细信息,即定义 vector 的真实命名空间不直接 std .
您可以通过其他漏洞检测嵌套命名空间(请参阅下面的注释),但内联命名空间会将它们全部插入 . 这就是它的全部内容 . 对于未来非常有用,但AFAIK标准没有规定其自己的标准库的内联命名空间名称(尽管我喜欢被证明是错误的),因此它只能用于第三方库,而不是标准本身(除非编译器供应商同意命名方案) .