Vì vậy, để tổng hợp các điểm chính using namespace v99
và inline namespace
không giống nhau, trước đây là giải pháp thay thế cho các thư viện phiên bản trước khi một từ khóa chuyên dụng (nội tuyến) được giới thiệu trong C ++ 11 nhằm khắc phục các vấn đề khi sử dụng using
, trong khi cung cấp chức năng phiên bản tương tự. Việc using namespace
sử dụng được sử dụng để gây ra sự cố với ADL (mặc dù ADL hiện có vẻ tuân theo các using
chỉ thị) và chuyên môn hóa ngoài luồng của một lớp / chức năng thư viện, v.v. bởi người dùng sẽ không hoạt động nếu được thực hiện bên ngoài không gian tên thật (có tên là người dùng sẽ không và không nên biết, tức là người dùng sẽ phải sử dụng B :: abi_v2 :: thay vì chỉ B :: để chuyên môn hóa giải quyết).
//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> {};
}
Điều này sẽ hiển thị một cảnh báo phân tích tĩnh first declaration of class template specialization of 'myclass' outside namespace 'A' is a C++11 extension [-Wc++11-extensions]
. Nhưng nếu bạn tạo không gian tên A nội tuyến, thì trình biên dịch sẽ giải quyết chính xác chuyên môn hóa. Mặc dù, với các phần mở rộng C ++ 11, vấn đề không còn nữa.
Các định nghĩa ngoài dòng không giải quyết khi sử dụng using
; chúng phải được khai báo trong khối không gian tên mở rộng lồng nhau / không lồng nhau (có nghĩa là người dùng cần biết lại phiên bản ABI, nếu vì bất kỳ lý do gì, chúng được phép cung cấp chức năng thực thi riêng của chúng).
#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
}
Vấn đề biến mất khi thực hiện B nội tuyến.
Các inline
không gian tên chức năng khác có cho phép người viết thư viện cung cấp bản cập nhật minh bạch cho thư viện 1) mà không buộc người dùng phải cấu trúc lại mã với tên không gian tên mới và 2) ngăn chặn sự thiếu tính chi tiết và 3) cung cấp sự trừu tượng hóa các chi tiết không liên quan đến API, trong khi 4) đưa ra chẩn đoán và hành vi liên kết có lợi tương tự mà sử dụng một không gian tên phi tuyến sẽ cung cấp. Giả sử bạn đang sử dụng thư viện:
namespace library {
inline namespace abi_v1 {
class foo {
}
}
}
Nó cho phép người dùng gọi library::foo
mà không cần biết hoặc bao gồm phiên bản ABI trong tài liệu, trông có vẻ sạch sẽ hơn. Sử dụng library::abiverison129389123::foo
sẽ trông bẩn.
Khi một bản cập nhật được thực hiện foo
, tức là thêm một thành viên mới vào lớp, nó sẽ không ảnh hưởng đến các chương trình hiện có ở cấp API vì chúng sẽ không sử dụng thành viên VÀ thay đổi trong tên không gian tên nội tuyến sẽ không thay đổi bất cứ điều gì ở cấp API bởi vì library::foo
vẫn sẽ làm việc
namespace library {
inline namespace abi_v2 {
class foo {
//new member
}
}
}
Tuy nhiên, đối với các chương trình liên kết với nó, vì tên không gian tên nội tuyến được chuyển thành tên biểu tượng như không gian tên thông thường, thay đổi sẽ không rõ ràng đối với trình liên kết. Do đó, nếu ứng dụng không được biên dịch lại mà được liên kết với một phiên bản mới của thư viện, nó sẽ xuất hiện một biểu tượngabi_v1
không tìm thấy lỗi, thay vì nó thực sự liên kết và sau đó gây ra lỗi logic bí ẩn khi chạy do không tương thích ABI. Thêm một thành viên mới sẽ gây ra khả năng tương thích ABI do thay đổi định nghĩa loại, ngay cả khi nó không ảnh hưởng đến chương trình tại thời gian biên dịch (cấp API).
Trong kịch bản này:
namespace library {
namespace abi_v1 {
class foo {
}
}
inline namespace abi_v2 {
class foo {
//new member
}
}
}
Giống như sử dụng 2 không gian tên phi tuyến, nó cho phép một phiên bản mới của thư viện được liên kết mà không cần biên dịch lại ứng dụng, bởi vì abi_v1
sẽ được đọc trong một trong các ký hiệu toàn cục và nó sẽ sử dụng định nghĩa loại chính xác (cũ). Tuy nhiên, việc biên dịch lại ứng dụng sẽ khiến các tham chiếu giải quyết library::abi_v2
.
Việc sử dụng using namespace
ít chức năng hơn so với sử dụng inline
(trong đó định nghĩa ngoài dòng không giải quyết được) nhưng cung cấp 4 lợi thế giống như trên. Nhưng câu hỏi thực sự là, tại sao tiếp tục sử dụng một cách giải quyết khi bây giờ đã có một từ khóa chuyên dụng để làm điều đó. Đó là cách thực hành tốt hơn, ít dài dòng hơn (phải thay đổi 1 dòng mã thay vì 2) và làm cho ý định rõ ràng.
using namespace V99;
không hoạt động trong ví dụ của Stroustrup.