Какова цель: использование пространства имен?

Существуют убедительные аргументы против using namespace std, так зачем же его вообще ввели в язык? Разве using namespace не противоречит цели пространств имен? Зачем мне вообще писать using namespace? Есть ли какая-то проблема, о которой я не знаю, и которая изящно решается с помощью using namespace, может быть, в строках идиомы using std::swap или что-то в этом роде?


person fredoverflow    schedule 05.12.2010    source источник
comment
Меньше печатать - довольно соблазнительный аргумент...   -  person    schedule 05.12.2010
comment
Концепция использования «using» работает в обход или против пространства имен, но она всегда рядом, когда вам это нужно.   -  person kenny    schedule 05.12.2010
comment
См. также статью Херба Саттера по Миграция в пространства имен.   -  person James McNellis    schedule 05.12.2010
comment
@James: Я немного не согласен с этой статьей :) Существующий код никогда не ломался из-за введения пространств имен в язык, потому что в то же время были изменены соглашения об именах для файлов заголовков. Поэтому, если ваши устаревшие коды делают #include <iostream.h>, то cin и cout прекрасно работают без квалификации std::. Так что миграция кода для меня точно не аргумент.   -  person fredoverflow    schedule 05.12.2010
comment
@Fred: Итак, игнорируйте краткосрочные решения. Правильное долгосрочное решение — полностью избегать использования директив, особенно в заголовочных файлах, и никогда не писать пространство имен с использованием объявлений в заголовочных файлах — отличный совет.   -  person James McNellis    schedule 05.12.2010
comment
(Трюк с поддержкой ADL using std::swap; описан в этот ответ to Что требует от меня объявить использование пространства имен std? (Существенно ли этот вопрос отличается от того вопроса? Я не знаю, является ли это точной копией, но они, похоже, охватывают одну и ту же тему .)   -  person James McNellis    schedule 05.12.2010


Ответы (6)


Во-первых, это способ использования перегруженных операторов в пространстве имен (например, using namespace std::rel_ops; или using namespace boost::assign;).

Краткость также является сильным аргументом. Вам действительно понравилось бы печатать и читать std::placeholders::_1 вместо _1? Кроме того, когда вы пишете код в функциональном стиле, вы будете использовать множество объектов в пространстве имен std и boost.

Другое важное использование (хотя обычно не импортируются целые пространства имен) — включить поиск, зависящий от аргумента:

template <class T>
void smart_swap(T& a, T& b)
{
    using std::swap;
    swap(a, b);
}

Если swap перегружен для некоторого типа T в том же пространстве имен, что и T, будет использоваться эта перегрузка. Если вместо этого вы явно вызвали std::swap, эта перегрузка не будет учитываться. Для других типов это возвращается к std::swap.

Кстати, использование объявления/директивы не противоречит цели пространств имен, поскольку вы всегда можете полностью уточнить имя в случае неоднозначности.

person UncleBens    schedule 05.12.2010
comment
Лично я согласен с использованием ‹X›, это использование пространства имен ‹X›, с которым у меня проблемы (за некоторыми исключениями, такими как rel_ops). - person Martin York; 05.12.2010

В большинстве случаев это просто ярлык для написания кода. Вы можете импортировать имена в окружающий контекст. Обычно я ограничиваю его .cpp файлами, потому что, когда вы включаете директиву using в .h файл, она загрязняет все файлы, в которые она включена. Другой хорошей практикой является ограничение using namespace максимально возможной закрытой средой, например, внутри объявления тела метода. Я рассматриваю это как удобство, не более, и похожее на псевдоним пространства имен, например:

namespace po = boost::program_options;

и тогда вы можете написать

po::variables_map ...
person Diego Sevilla    schedule 05.12.2010

Основной причиной, по которой был введен using namespace, была обратная совместимость: если у вас есть много кода до пространства имен, использующего множество (достандартных версий) стандартных библиотечных функций и классов, вам нужен простой способ заставить этот код работать с соответствующим стандарту. компилятор.

Кстати, правила поиска, зависящие от аргумента, по крайней мере, для C++98 означают, что using namespace std::rel_ops не будет делать то, что вы хотите в шаблонах (я не знаю, изменилось ли это в более поздней версии стандарта).

Пример:

template<typename T> bool bar(T t)
{
  return t > T();
}

namespace foo
{
  class X {};
  bool operator<(X, X);
}

using namespace std::rel_ops;

int main()
{
  X x;
  bar(x); // won't work: X does not have operator>
}

Обратите внимание, что установка using namespace в namespace foo тоже не поможет.

Однако правильное использование объявлений помогает:

template<typename T> bool bar(T t)
{
  return t > T();
}

namespace foo
{
  class X {};
  bool operator<(X, X);
  using std::rel_ops::operator>;
}

int main()
{
  X x;
  bar(x); // now works: operator> found per ADL via the using declaration in `namespace foo`
}
person celtschk    schedule 15.07.2013

Люди конкретно возражают против using namespace std;, но не против using namespace BigCorp; или ссылаться на std::cout (которое использует пространство имен, а не using его, если вы понимаете, о чем я.) Кроме того, большинство возражений против using namespace std находятся в заголовочном файле. В исходном файле, где эффекты видны сразу, это менее вредно.

Пространства имен — невероятно полезная концепция, которая позволяет мне иметь класс с именем Date, даже если библиотека, которую я использую, имеет класс с именем Date. Прежде чем они были добавлены в язык, у нас должны были быть такие вещи, как GCDate и GCString (моя компания, Gregory Consulting, предшествует std::string). Использование пространств имен (с ключевым словом using или без него) позволяет всем нам писать более чистый и аккуратный код. Но когда вам приходится говорить Gregcons::string каждый раз, вы как бы теряете более чистую и аккуратную часть. [Отказ от ответственности: на самом деле я больше не использую свой собственный строковый класс — представьте какой-нибудь подходящий конфликт имен.] В этом привлекательность оператора using. Держите его подальше от заголовков, не применяйте его к std, и вообще у вас не должно быть проблем.

person Kate Gregory    schedule 05.12.2010
comment
Я бы сказал, используйте не using namespace foo, а using foo::whatever; это относится как к стандартным, так и к другим именам. Например, нет ничего плохого в using std::cout, если это не сделано в заголовке. - person celtschk; 15.07.2013

Я нахожу это полезным при работе с библиотеками с глубоко вложенными пространствами имен. Библиотека Boost является одним из таких примеров. Представляю, как везде печатают boost::numeric::ublas::matrix<double> m...

Чего следует избегать, так это делать using namespace в заголовочном файле, так как это может сильно испортить любую программу, которая включает указанный заголовок. Всегда размещайте операторы using namespace в файлах .cpp/.cxx, чтобы они ограничивались областью действия файла.

person CadentOrange    schedule 05.12.2010
comment
но псевдоним пространства имен также может решить эту проблему. Или вы можете просто выборочно импортировать только matrix. - person jalf; 06.12.2010
comment
Или вы можете использовать typedef, например. typedef boost::numeric::ublas::matrix<double> DoubleMatrix и используйте DoubleMatrix в остальной части кода. В этом красота/проклятие C++: есть несколько подходов к решению одной и той же проблемы. - person CadentOrange; 06.12.2010

«Пространства имен позволяют группировать сущности, такие как классы, объекты и функции, под именем. Таким образом, глобальная область может быть разделена на «подобласти», каждая из которых имеет свое собственное имя. Где идентификатор — это любой допустимый идентификатор, а сущности — это набор классы, объекты и функции, включенные в пространство имен"

Дополнительная информация здесь: http://www.cplusplus.com/doc/tutorial/namespaces/

person pwnedu46    schedule 05.12.2010