2015-10-13 20 views
28
using ::std::...; 

VSkhác biệt trong việc sử dụng không gian tên (std :: vs :: std: :)

using std::...; 

Có một sự khác biệt (s)? Nếu có, cái nào?

Tôi thấy điều này:

using ::std::nullptr_t; 

mà làm cho tôi băn khoăn.

+12

Bạn chỉ cần viết ':: std :: nullptr_t' chỉ khi người khác thêm một' std :: nullptr_t' vào một vùng tên lồng nhau bên trong dự án của bạn. Hoặc bạn có thể để người quản lý của bạn có một cuộc nói chuyện ** nghiêm túc ** với anh chàng đó. –

+3

BTW a 'không gian tên C14_compatibility {namespace std {template sử dụng decay_t = typename decay :: type; }} 'và' sử dụng không gian tên C14_compatibility; 'có vẻ là một cách sử dụng có thể. – Jarod42

+0

Hoặc thực sự, khi trình biên dịch của bạn không hỗ trợ chuẩn C++ mà bạn muốn sử dụng, hoặc nó thực hiện nhưng bạn cần thực hiện của riêng bạn ở một số nơi. – OrangeDog

Trả lời

31

Trong trường hợp của bạn, hầu như không có sự khác biệt. Tuy nhiên, nhìn chung, sự khác biệt như sau:

using A::foo; giải quyết A từ phạm vi hiện tại, trong khi using ::A::foo tìm kiếm A từ namespace root.Ví dụ:

namespace A 
{ 
    namespace B 
    { 
     class C; 
    } 
} 
namespace B 
{ 
    class C; 
} 
namespace A 
{ 
    using B::C; // resolves to A::B::C 
    using ::B::C; // resolves to B::C 
    // (note that one of those using declarations has to be 
    // commented for making this valid code!) 
} 
+2

Sự khác biệt này rất quan trọng khi viết macro. Macro được mở rộng bất cứ nơi nào nhà phát triển sử dụng. Macro không thể giả sử 'std' đi đúng nơi nó muốn, vì vậy các macro thường sẽ sử dụng' :: std' để đảm bảo rằng macro không có bất kỳ bất ngờ bất ngờ nào. –

8

Từ: http://en.cppreference.com/w/cpp/language/using_declaration

Sử dụng-khai giới thiệu một thành viên của không gian tên khác vào namespace hiện tại hoặc chặn phạm vi

Do đó, nếu phạm vi hiện tại của bạn đã có một lớp có cùng tên, sẽ có một sự mơ hồ giữa một trong những bạn giới thiệu và một trong không gian tên/khối hiện tại của bạn.

Tuyên bố sử dụng chỉ là tập con của chỉ thị sử dụng. Các chỉ thị sử dụng được định nghĩa như sau (http://en.cppreference.com/w/cpp/language/namespace):

Từ quan điểm của tra cứu tên không đủ tiêu chuẩn của tên bất kỳ sau một sử dụng-chỉ thị và cho đến cuối phạm vi trong đó nó xuất hiện, mỗi tên từ namespace-name được hiển thị như thể nó đã được khai báo trong không gian tên bao quanh gần nhất chứa cả hai tên sử dụng-chỉ thị và không gian tên.

Vì vậy, bạn có thể xem xét hai ví dụ này hiển thị các vấn đề có thể phát sinh.

Nó ngăn không rõ ràng giữa các không gian tên có chung tên (ví dụ 1) cũng như sự mơ hồ giữa các tên lớp trong các không gian tên khác nhau (ví dụ 2).

namespace A 
{ 
    namespace B 
    { 
     struct my_struct {}; 
    } 
} 

namespace B 
{ 
    struct my_struct {}; 
} 

using namespace A; // removing this line makes B:: resolve to the global B:: 

int main() 
{ 
    ::B::my_struct; // from global, will not pick A::B:: 

    B::my_struct; // error: 'B' is ambiguous, there is A::B:: and B:: 
} 

Hãy xem xét ví dụ này nơi trưng bày lý do tại sao mọi người tránh xa việc sử dụng using namespace std;

using namespace std; 

template <typename T> 
class vector 
{ }; 

int main() 
{ 
    vector<int> v; // which one did you want? ambiguous 
    ::vector<int> v_global;  // global one 
    ::std::vector<int> v_std; // std::vector<T> 
} 
+0

Chỉ thị sử dụng được sử dụng như thế nào trong trường hợp này để làm cho nó phù hợp với câu hỏi? – dspfnder

+0

Nói chung điều này là đúng, nhưng câu hỏi này là về các kiểu 'using' từ một không gian tên, không phải toàn bộ không gian tên! – anderas

+0

@anderas Sự khác biệt giữa khai báo sử dụng và chỉ thị sử dụng không lớn. Bạn có thể chỉ đơn giản là xem nó như là một trong những giới thiệu một loại duy nhất vào phạm vi hiện tại và khác giới thiệu tất cả các loại vào phạm vi hiện hành. –

5

Nó phụ thuộc vào nơi bạn sử dụng tờ khai using. Trên phạm vi không gian tên chung sẽ không có sự khác biệt. Tuy nhiên, nếu bạn có mã như

#include <iostream> 
#include <vector> 

namespace my_namespace { 
    namespace std { 
     class vector { 
     }; 
    } 

    using std::vector; 
} 

int main() 
{ 
    my_namespace::vector<int> v; 
} 

nó sẽ không biên dịch, trừ khi bạn thông báo cho trình biên dịch để tìm kiếm trên không gian tên toàn cầu -> std namespace -> vector trong tuyên bố của mình bằng cách nói using ::std::vector.

+2

Mặt khác, mọi người thêm một không gian tên bổ sung 'std' vào nguồn xứng đáng để bị sa thải. Đó là dễ dàng hơn nhiều so với việc mọi người khác viết ':: std ::' khắp nơi. –

+0

@BoPersson Tất nhiên :) Tôi chỉ minh họa sự khác biệt. Nó có lẽ chỉ là ưu tiên của nhà phát triển để viết ':: std :: ...'. – Rostislav

+0

@BoPersson: Tôi đã thêm nhận xét trong câu hỏi của OP có vẻ như là một lý do khả thi để có 'không gian tên std' bên trong không gian tên người dùng. – Jarod42

10

Nếu bạn đang ở trong một không gian tên có lồng std namespace riêng của mình, sau đó ::stdstd là khác nhau. Một ví dụ đơn giản:

#include <iostream> 

namespace A { 
    namespace std { 
     void foo() { ::std::cout << "foo" << ::std::endl;} 
    } 
    //using std::cout; // compile error 
    using ::std::cout; //ok 

    using std::foo; // ok 
    //using ::std::foo; // compile error 
} 

Mặc dù chắc chắn không phải là thực tiễn tốt để có không gian tên lồng nhau std.

+0

Vì vậy, ':: std ::' nói để có không gian tên toàn cục hơn của std? Ồ, Andreas làm rõ câu trả lời của anh ấy, cảm ơn, +1. – gsamaras

+3

@gsamaras, không chỉ toàn cầu hơn, mà là cái duy nhất hoàn toàn toàn cầu, không được lồng vào bất cứ đâu. – Petr

Các vấn đề liên quan