Ответ 1
Это зависит.
Если вы хотите вставить одно имя в другую область видимости, лучше использовать объявление-декларацию, например
namespace foolib
{
// allow vector to be used unqualified within foo,
// or used as foo::vector
using std::vector;
vector<int> vec();
template<typename T> struct Bar { T t; };
template<typename T>
void swap(Bar<T>& lhs, Bar<T>& rhs)
{
using std::swap;
// find swap by ADL, otherwise use std::swap
swap(lhs.t, rhs.t);
}
}
Но иногда вам просто нужны все имена, что и делает директива using. Это можно использовать локально в функции или глобально в исходном файле.
Помещение using namespace
вне тела функции должно выполняться только там, где вы точно знаете, что включено, поэтому оно безопасно (т.е. не) в заголовке, где вы не знаете, что будет включено до или после этого заголовка), хотя многие люди все еще недовольны этим использованием (читайте ответы на Почему "using namespace std" считается плохой практикой? для деталей):
#include <vector>
#include <iostream>
#include "foolib.h"
using namespace foo; // only AFTER all headers
Bar<int> b;
Причиной использования директивы using является то, что пространство имен содержит только небольшое количество имен, которые сохраняются намеренно разделенными и предназначены для использования с помощью директивы-указателя:
#include <string>
// make user-defined literals usable without qualification,
// without bringing in everything else in namespace std.
using namespace std::string_literals;
auto s = "Hello, world!"s;
Таким образом, нет единого ответа, который может сказать, что один универсален лучше другого, у них разные виды использования, и каждый из них лучше в разных контекстах.
Что касается первого использования using namespace
, то создатель С++, Bjarne Stroustrup, имеет это сказать в §14.2.3 языка программирования С++, 4-е изд. (выделено мной):
Часто нам нравится использовать любое имя из пространства имен без квалификации. Это может быть достигнуто путем предоставления
using
-declaration для каждого имени из пространства имен, но это утомительно и требует дополнительной работы каждый раз, когда новое имя добавляется или удаляется из пространства имен. В качестве альтернативы мы можем использовать директивуusing
, чтобы запросить, чтобы каждое имя из пространства имен было доступно в нашей области без квалификации. [...]
[...] Использованиеusing
-directive для создания имен из часто используемой и хорошо известной библиотеки, доступной без квалификации, является популярным методом упрощения кода. Это метод, используемый для доступа к средствам стандартной библиотеки в этой книге. [...]
Внутри функции директивуusing
можно безопасно использовать в качестве нотации, но следует соблюдать глобальные директивыusing
, поскольку чрезмерное использование может привести к точному конфликту имен, которые были введены для пространств имен. [...]
Следовательно, мы должны быть осторожны сusing
-directives в глобальной области. В частности, не размещайте директивуusing
в глобальной области видимости в файле заголовка, за исключением особых условий (например, для перехода на переход), потому что вы никогда не знаете, где заголовок может быть#include
d.
Мне кажется, это гораздо лучший совет, чем просто настаивать на том, что он плох и его не следует использовать.