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.
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.
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!)
}
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. –
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>
}
Come utilizzare la direttiva using in questo caso per renderla coerente con la domanda? – dspfnder
Generalmente questo è vero, ma questa domanda riguarda i tipi 'using' da un namespace, non l'intero namespace! – anderas
@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. –
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
.
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. –
@BoPersson Certo :) Stavo solo illustrando la differenza. Probabilmente è solo la preferenza degli sviluppatori di scrivere ':: std :: ...'. – Rostislav
@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
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.
È 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. –
BTW a 'namespace C14_compatibility {namespace std {template utilizzando decay_t = typename decay :: type; }} 'e' using namespace C14_compatibility; 'sembra un possibile utilizzo. –
Jarod42
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