什么是内联命名空间?
C ++ 11允许inline namespace
,其所有成员也都自动位于封闭namespace
。 我想不出任何有用的应用程序 – 有人可以请一个简短,简洁的例子,一个inline namespace
是必要的,它是最习惯的解决scheme?
(另外,我不清楚当一个namespace
在一个声明中是inline
,而不是所有的声明,这些声明可能存在于不同的文件中,这不是乞求麻烦吗?)
内联命名空间是类似于符号版本控制的库版本控制function,但纯粹在C ++ 11级(即跨平台)上实现,而不是作为特定二进制可执行格式(即特定于平台)的function。
这是一个库作者可以使一个嵌套的名称空间外观和行为,就好像它的所有声明在周围的命名空间(内联命名空间可以嵌套,所以“更多嵌套”名称渗透到第一个非内联命名空间,看起来和行为,就好像他们的声明也在任何之间的命名空间)。
作为例子,考虑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> // eg 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
的值, __cplusplus
一个或另一个vector
实现。 如果你的代码库是用C ++语言编写的,那么当你升级你的编译器时,你所要做的就是find引用std::vector
在你的代码库中,并将其replace为std::pre_cxx_1997::vector
。
来下一个标准,STL供应商再次重复这个过程,引入一个新的命名空间为std::vector
emplace_back
支持(这需要C ++ 11),并内联一个iff __cplusplus == 201103L
。
好的,为什么我需要一个新的语言function呢? 我已经可以做到以下效果了,不是吗?
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
这是完全有效的代码,其中用户提供了自己的一个types的vector的实现,她显然知道比STL(她的副本)中find的更有效的实现。
但是 :专门化模板时,需要在声明的名称空间中执行此操作。标准说明了vector
是在名称空间std
声明的,所以这是用户正确地期望专用于该types的地方。
此代码可以与非版本化命名空间std
或C ++ 11内联命名空间function一起使用,但不能与using namespace <nested>
的版本控制技巧一起使用,因为这会公开实际的命名空间,定义不是std
直接。
还有其他的漏洞可以用来检测嵌套的命名空间(见下面的注释),但是内联的命名空间将它们全部插入。 这就是它的一切。 非常有用的未来,但AFAIK标准并没有规定内联命名空间名称为自己的标准库(我喜欢被certificate是错误的,虽然),所以它只能用于第三方库,而不是标准本身(除非编译器厂商同意命名scheme)。
http://www.stroustrup.com/C++11FAQ.html#inline-namespace (由Bjarne Stroustrup编写和维护的文档,您认为应该了解大多数C ++ 11function的大部分动机。 )
据此,允许向后兼容版本化。 您可以定义多个内部命名空间,并使其inline
最近的一个。 无论如何,对于那些不关心版本控制的人来说,这是默认的。 我想最近的一个可能是一个未来或尖端的版本,这是不是默认的。
给出的例子是:
// file V99.h: inline namespace V99 { void f(int); // does something better than the V98 version void f(double); // new feature // ... } // file V98.h: namespace V98 { void f(int); // does something // ... } // file Mine.h: namespace Mine { #include "V99.h" #include "V98.h" } #include "Mine.h" using namespace Mine; // ... V98::f(1); // old version V99::f(1); // new version f(1); // default version
我不明白为什么你不using namespace V99;
在我的命名空间里面,但是我并不需要完全理解这个用例,以便把Bjarne的话放在委员会的动机上。