Yani ana noktaları özetlemek için using namespace v99
ve inline namespace
aynı değildi, eski kullanarak sorunlarını sabit C ++ 11'de tanıtıldı özel bir anahtar kelime (inline) önce versiyon kütüphaneleri için bir geçici çözüm oldu using
aynı sürüm işlevselliği sunarken,. Kullanma using namespace
ADL ile neden problemlerine kullanılan (ADL şimdi izleyin görünse de using
direktifler) ve dışı hattı vb kütüphane sınıf / fonksiyon uzmanlık kullanıcı tarafından değil iş olan gerçek ad alanının bitti dışında (isim olsaydı kullanıcı bilmeyecek ve bilmeyecektir, yani kullanıcı, uzmanlığın çözülmesi için B :: yerine B :: abi_v2 :: kullanmalıdır).
//library code
namespace B { //library name the user knows
namespace A { //ABI version the user doesn't know about
template<class T> class myclass{int a;};
}
using namespace A; //pre inline-namespace versioning trick
}
// user code
namespace B { //user thinks the library uses this namespace
template<> class myclass<int> {};
}
Bu statik bir analiz uyarısı gösterecektir first declaration of class template specialization of 'myclass' outside namespace 'A' is a C++11 extension [-Wc++11-extensions]
. Ancak, ad alanı A satır içi yaparsanız, derleyici uzmanlığı doğru bir şekilde çözer. Bununla birlikte, C ++ 11 uzantılarında sorun ortadan kalkar.
Hat dışı tanımlar kullanılırken çözülmez using
; iç içe / iç içe olmayan bir uzantı ad alanı bloğunda bildirilmeleri gerekir (bu, herhangi bir nedenle, bir işlevi kendi uygulamalarını sağlamalarına izin verildiyse, kullanıcının ABI sürümünü tekrar bilmesi gerektiği anlamına gelir).
#include <iostream>
namespace A {
namespace B{
int a;
int func(int a);
template<class T> class myclass{int a;};
class C;
extern int d;
}
using namespace B;
}
int A::d = 3; //No member named 'd' in namespace A
class A::C {int a;}; //no class named 'C' in namespace 'A'
template<> class A::myclass<int> {}; // works; specialisation is not an out-of-line definition of a declaration
int A::func(int a){return a;}; //out-of-line definition of 'func' does not match any declaration in namespace 'A'
namespace A { int func(int a){return a;};} //works
int main() {
A::a =1; // works; not an out-of-line definition
}
B sıralı yapılırken sorun ortadan kalkar.
Diğer işlev inline
ad alanları, kütüphane yazarının 1) kullanıcıyı yeni ad alanı adıyla kodu yeniden düzenlemeye zorlamadan ve 2) ayrıntı eksikliğini önleme ve 3) API ile ilgili olmayan ayrıntıların soyutlanmasını sağlamadan kütüphaneye şeffaf bir güncelleme sağlamasına izin verir, 4) ise, satır içi olmayan bir ad alanı kullanmanın sağlayabileceği aynı yararlı bağlayıcı tanı ve davranışını vermek. Bir kütüphane kullandığınızı varsayalım:
namespace library {
inline namespace abi_v1 {
class foo {
}
}
}
Kullanıcının library::foo
, daha temiz görünen belgelerdeki ABI sürümünü bilmesine veya eklemesine gerek kalmadan arama yapmasına olanak tanır . Kullanmak library::abiverison129389123::foo
kirli görünecektir.
Bir güncelleme yapıldığında foo
, yani sınıfa yeni bir üye eklendiğinde, zaten üyeyi kullanmayacakları için API düzeyinde mevcut programları etkilemez VE satır içi ad alanı adındaki değişiklik API düzeyinde hiçbir şey değiştirmez çünkü library::foo
hala çalışacak.
namespace library {
inline namespace abi_v2 {
class foo {
//new member
}
}
}
Bununla birlikte, onunla bağlantı kuran programlar için, satır içi ad alanı adı normal ad alanı gibi sembol adlarına karıştırıldığı için, değişiklik bağlayıcıya saydam olmaz. Bu nedenle, uygulama yeniden derlenmemişse ancak kitaplığın yeni bir sürümüyle abi_v1
bağlantılıysa, ABI uyumsuzluğu nedeniyle çalışma zamanında gerçekte bağlanmak ve daha sonra gizemli bir mantık hatasına neden olmak yerine hata bulunmayan bir sembol sunar . Yeni bir üye eklemek, programı derleme zamanında etkilemese bile (API düzeyi) tür tanımındaki değişiklik nedeniyle ABI uyumluluğuna neden olur.
Bu senaryoda:
namespace library {
namespace abi_v1 {
class foo {
}
}
inline namespace abi_v2 {
class foo {
//new member
}
}
}
Satır içi 2 olmayan ad alanı kullanmak gibi, uygulamanın yeniden derlenmesine gerek kalmadan kütüphanenin yeni bir sürümünün bağlanmasına izin verir, çünkü abi_v1
genel sembollerden birinde karıştırılır ve doğru (eski) tür tanımını kullanır. Ancak uygulamanın yeniden derlenmesi, başvuruların çözümlenmesine neden olur library::abi_v2
.
Kullanmak using namespace
, kullanmaktan daha az işlevseldir inline
(hat dışı tanımlar çözülmez), ancak yukarıdaki ile aynı 4 avantajı sağlar. Ancak asıl soru, şimdi bunu yapmak için özel bir anahtar kelime olduğunda neden bir geçici çözüm kullanmaya devam etmektir. Daha iyi uygulama, daha az ayrıntılı (2 yerine 1 kod satırını değiştirmek zorunda) ve niyeti açıklığa kavuşturuyor.
using namespace V99;
Stroustrup örneğinde neden çalışmadığını açıklayan +1 .