Primeiro, algumas terminologias:
- declaração de uso :
using std::vector;
- using-Directive :
using namespace std;
Acho que usar as diretivas de uso é bom, desde que não sejam usadas no escopo global em um arquivo de cabeçalho. Então tendo
using namespace std;
no seu arquivo .cpp não é realmente um problema e, se for o caso, está completamente sob seu controle (e pode até mesmo ter como escopo blocos específicos, se desejado). Não vejo nenhuma razão particular para confundir o código com uma série de std::
qualificadores - torna-se apenas um monte de ruído visual. No entanto, se você não estiver usando um monte de nomes dostd
namespace em seu código, também não vejo problema em a diretiva. É uma tautologia - se a diretiva não for necessária, não há necessidade de usá-la.
Da mesma forma, se você pode sobreviver com algumas declarações de uso (em vez de diretivas de uso ) para tipos específicos no std
namespace, então não há razão para que você não deva ter apenas esses nomes específicos trazidos para o namespace atual. Da mesma forma, acho que seria uma loucura e um aborrecimento contábil ter 25 ou 30 declarações de uso quando uma única diretiva de uso faria o mesmo bem.
Também é bom ter em mente que há momentos em que você deve usar uma declaração de uso. Consulte o "Item 25: Considere o suporte para uma troca sem lançamento" de Scott Meyers em Effective C ++, Third Edition. Para que uma função genérica e modelada use o 'melhor' método de troca para um tipo parametrizado, você precisa fazer uso de uma declaração de uso e pesquisa dependente de argumento (também conhecida como pesquisa ADL ou Koenig):
template< typename T >
void foo( T& x, T& y)
{
using std::swap; // makes std::swap available in this function
// do stuff...
swap( x, y); // will use a T-specific swap() if it exists,
// otherwise will use std::swap<T>()
// ...
}
Acho que devemos olhar para os idiomas comuns para várias linguagens que fazem uso significativo de namespaces. Por exemplo, Java e C # usam namespaces em grande medida (possivelmente mais do que C ++). A forma mais comum pela qual os nomes dentro de namespaces são usados nessas linguagens é trazendo-os para o escopo atual em massa com o equivalente a uma diretiva using. Isso não causa problemas generalizados e, nas poucas vezes em que é um problema, é tratado como uma 'exceção', lidando com os nomes em questão por meio de nomes totalmente qualificados ou por aliasing - exatamente como pode ser feito em C ++.
Herb Sutter e Andrei Alexandrescu têm a dizer isso no "Item 59: Não escreva usos de namespace em um arquivo de cabeçalho ou antes de um #include" de seu livro, Padrões de Codificação C ++: 101 Regras, Diretrizes e Melhores Práticas:
Resumindo: você pode e deve usar o namespace usando declarações e diretivas livremente em seus arquivos de implementação após as #include
diretivas e se sentir bem com isso. Apesar das repetidas afirmações em contrário, os namespaces que usam declarações e diretivas não são nocivos e não anulam o propósito dos namespaces. Em vez disso, são eles que tornam os namespaces utilizáveis.
Stroupstrup é frequentemente citado como dizendo, "Não polua o namespace global", em "The C ++ Programming Language, Third Edition". Ele de fato diz isso (C.14 [15]), mas se refere ao capítulo C.10.1 onde diz:
Uma declaração de uso adiciona um nome a um escopo local. Uma diretiva de uso não; ele simplesmente torna os nomes acessíveis no escopo em que foram declarados. Por exemplo:
namespaceX {
int i , j , k ;
}
int k ;
void f1()
{
int i = 0 ;
using namespaceX ; // make names from X accessible
i++; // local i
j++; // X::j
k++; // error: X::k or global k ?
::k ++; // the global k
X::k ++; // X’s k
}
void f2()
{
int i = 0 ;
using X::i ; // error: i declared twice in f2()
using X::j ;
using X::k ; // hides global k
i++;
j++; // X::j
k++; // X::k
}
Um nome declarado localmente (declarado por uma declaração comum ou por uma declaração de uso) oculta declarações não locais do mesmo nome e quaisquer sobrecargas ilegais do nome são detectadas no ponto da declaração.
Observe o erro de ambiguidade para k++
em
f1()
. Nomes globais não têm preferência sobre nomes de namespaces acessíveis no escopo global. Isso fornece proteção significativa contra conflitos de nomes acidentais e, mais importante, garante que não haja vantagens em poluir o namespace global.
Quando as bibliotecas que declaram muitos nomes se tornam acessíveis por meio de diretivas de uso, é uma vantagem significativa que os confrontos de nomes não usados não sejam considerados erros.
...
Espero ver uma redução radical no uso de nomes globais em novos programas que usam namespaces em comparação com os programas C e C ++ tradicionais. As regras para namespaces foram criadas especificamente para não dar vantagens a um usuário '' preguiçoso '' de nomes globais sobre alguém que toma cuidado para não poluir o escopo global.
E como alguém tem a mesma vantagem de um 'usuário preguiçoso de nomes globais'? Tirando vantagem da diretiva using, que disponibiliza com segurança os nomes em um namespace para o escopo atual.
Observe que há uma distinção - nomes no std
namespace disponibilizados para um escopo com o uso adequado de uma diretiva using (colocando a diretiva após o #includes
) não poluem o namespace global. É apenas disponibilizar esses nomes facilmente e com proteção contínua contra confrontos.