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

VSDifferenza di using namespace (std :: :: vs std: :)

using std::...; 

C'è una differenza (s)? Se sì, quale/i?

ho visto questo:

using ::std::nullptr_t; 

che mi ha fatto chiedo.

+12

È necessario scrivere ':: std :: nullptr_t' solo se qualcun altro aggiunge un altro' std :: nullptr_t' a uno spazio dei nomi annidato all'interno del progetto. Oppure potresti lasciare che il tuo manager abbia un ** serio ** discorso con quel tipo. –

+3

BTW a 'namespace C14_compatibility {namespace std {template utilizzando decay_t = typename decay :: type; }} 'e' using namespace C14_compatibility; 'sembra un possibile utilizzo. – Jarod42

+0

O in effetti, quando il compilatore non supporta lo standard C++ che si desidera utilizzare, oppure lo fa, ma in alcuni punti è necessaria la propria implementazione. – OrangeDog

risposta

31

Nel tuo caso, molto probabilmente non c'è differenza. Tuttavia, in generale, la differenza è la seguente:

using A::foo; risolve A dagli attuali portata , mentre using ::A::foo cercati A dalla spazio principale.Per esempio:

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

Questa differenza è molto importante quando si scrivono macro. Una macro è espansa ovunque lo sviluppatore lo usi. La macro non può assumere che 'std' vada esattamente dove vuole, quindi le macro useranno spesso' :: std' per assicurarsi che la macro non abbia sorprese inaspettate. –

8

Da: http://en.cppreference.com/w/cpp/language/using_declaration

dichiarazione using introduce un membro di un altro spazio dei nomi in namespace corrente o bloccare portata

Pertanto, se l'ambito attuale ha già una classe con lo stesso nome, ci sarà un'ambiguità tra quello che hai introdotto e quello nel tuo attuale namespace/blocco.

Una dichiarazione di utilizzo è solo un sottoinsieme di una direttiva using. Le direttive using è definito come segue (http://en.cppreference.com/w/cpp/language/namespace):

Dal punto di vista della ricerca del nome qualificato di ogni nome dopo una using-direttiva e fino alla fine dell'ambito in cui compare, ogni nome da namespace-name è visibile come se fosse stato dichiarato in lo spazio dei nomi più vicino che contiene sia il using-directive e namespace-name.

Pertanto, è possibile considerare questi due esempi che mostrano i problemi che possono sorgere.

Impedisce l'ambiguità tra gli spazi dei nomi che condividono lo stesso nome (esempio 1) e l'ambiguità tra i nomi di classe in diversi spazi dei nomi (esempio 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:: 
} 

Si consideri l'esempio che mette in mostra il motivo per cui le persone evitano l'uso di 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

Come utilizzare la direttiva using in questo caso per renderla coerente con la domanda? – dspfnder

+0

Generalmente questo è vero, ma questa domanda riguarda i tipi 'using' da un namespace, non l'intero namespace! – anderas

+0

@anderas La differenza tra una dichiarazione using e una direttiva using non è così grande. Si può semplicemente vederlo come si introduce un singolo tipo nello scope corrente e l'altro introduce tutti i tipi nello scope corrente. –

5

Dipende da dove si utilizza la dichiarazione using. In un ambito di namespace globale non ci saranno differenze. Tuttavia, se si dispone di un codice simile

#include <iostream> 
#include <vector> 

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

    using std::vector; 
} 

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

non si compila a meno che non si informa il compilatore per cercare il namespace globale -> namespace std -> vettore nella dichiarazione affermando using ::std::vector.

+2

D'altra parte, le persone che aggiungono uno spazio dei nomi aggiuntivo 'std' all'origine meritano di essere licenziati. È molto più facile che avere tutti gli altri scrivendo ':: std ::' dappertutto. –

+0

@BoPersson Certo :) Stavo solo illustrando la differenza. Probabilmente è solo la preferenza degli sviluppatori di scrivere ':: std :: ...'. – Rostislav

+0

@BoPersson: Ho aggiunto un commento nella domanda dell'OP che sembra un valido motivo per avere 'namespace std' all'interno dello spazio dei nomi utente. – Jarod42

10

Se sei all'interno di un altro spazio dei nomi che ha il suo nidificato std spazio dei nomi, quindi ::std e std sono diversi. Un semplice esempio:

#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 
} 

Anche se sicuramente non è una buona pratica per avere sempre un nidificato std namespace.

+0

Quindi ':: std ::' dice di assumere lo spazio dei nomi più globale di std? Oh, Andreas chiarisce la sua risposta, grazie però, +1. – gsamaras

+3

@gsamaras, non solo il più globale, ma (solo) quello che è assolutamente globale, non annidato da nessuna parte. – Petr

Problemi correlati