Все директивы использования рассматриваются так же, как использование пространства имен std?

Я легко привык ставить перед стандартными идентификаторами префикс std:: вместо using namespace std;. Тем не менее, я начал изучать C# и заметил, что вполне нормально добавлять все необходимые директивы использования, т. е. вы увидите:

using System;
Console.Write("foo");

вместо:

System.Console.Write("foo");

По-видимому, как я узнал из вопроса С# по этой теме, это использование связано с тем, что отдельные системные пространства имен в С# намного, намного меньше, чем std в С++, и, следовательно, устраняет проблемы, связанные с конфликтами имен, поскольку существует гораздо меньшая вероятность (и вы можете просто найти-заменить его полным именем, если библиотека обновляется с конфликтом имен), и устраняет проблемы, связанные с появлением множества опций Intellisense, поскольку пространства имен достаточно малы для обработки.

Тогда возникает вопрос: если это основные причины использования директив using в C#, верно ли то же самое для C++? В целом приемлемо ли применять это к меньшим сторонним пространствам имен, а также к вашим собственным меньшим пространствам имен?

Теперь я понимаю, что это может вызвать небольшое противоречие, я хочу воспользоваться моментом, чтобы попросить, чтобы это не превратилось в спор. Хороший ответ должен включать в себя основу, т. е. преимущества или недостатки, а также то, как использование одного способа вместо другого действительно имеет важное значение.

Причина, по которой я задаю этот вопрос, заключается в том, чтобы прояснить проблему и, возможно, устранить представление о том, что использование директив в C++ должно быть плохим. Конечно, более длинные имена пространств имен можно при необходимости сократить с помощью псевдонима пространства имен, и при необходимости все еще можно использовать полные имена, но иногда директива using значительно облегчает доступ к некоторым членам, таким как пользовательские литеральные операторы, которые, насколько мне известно, не имеют формы ADL, а это означает, что вам нужно либо использовать директиву using, либо вызывать метод оператора с помощью синтаксиса функции, что в первую очередь сводит на нет всю цель использования оператора.

Например, у меня было пространство имен (которое включает в себя структуру, представляющую клавишу клавиатуры, вместе с литеральным суффиксом в качестве удобочитаемого альтернативного средства доступа:

"caps lock"_key.disable();

Проблема здесь в том, что если вы ранее не вставили using namespace Whatever; или using Whatever::operator"" _key;, код не скомпилируется, что является плохой новостью для пользователя.

Использование директив имеет очевидные проблемы, когда задействовано std или когда они используются в заголовке таким образом, что они привносят нежелательные дополнения для пользователя этого заголовка, но оправдано ли их использование для других пространств имен, когда они содержатся в меньшей области, чем все, что включает заголовок? Нажатия клавиш, избавленные от необходимости вводить каждый квалификатор каждый раз, действительно складываются, и с современными возможностями Intellisense выяснить, к какому пространству имен принадлежит неквалифицированный идентификатор, так же просто, как навести на него курсор мыши.


person chris    schedule 04.09.2012    source источник
comment
Помните, что в C# нет проблем (функций) с файлами заголовков, которые есть в C++, поэтому там устраняется целый класс проблем.   -  person Martin York    schedule 04.09.2012
comment
@LokiAstari, очень хороший момент. Разве C++ не пытается перестроить систему #include для следующего обновления языка?   -  person chris    schedule 04.09.2012


Ответы (1)


Я думаю, что правила использования объявлений в C++ довольно просты:

  1. НИКОГДА не пишите «используя пространство имен»; в глобальной области заголовка, особенно тот, который может быть повторно использован другими программами (например, при написании библиотеки). Он загрязняет глобальную область видимости всех последующих заголовков символами этого пространства имен, что сводит на нет всю цель пространств имен и впоследствии может привести к непредвиденным конфликтам имен.
  2. В файлах .cpp и внутренних областях заголовков (например, встроенных функциях) вы можете «использовать» любые пространства имен, которые вы хотите, поскольку это не повлияет на любой другой файл. Просто делайте то, что вам удобнее, и старайтесь быть разумно последовательным в рамках проекта.

РЕДАКТИРОВАТЬ: для проблемы с _key просто определите этот оператор в его собственном пространстве имен и попросите пользователей импортировать его. Таким образом, им не нужно будет вводить объявление оператора.

namespace something {
class key { ... };
}
namespace key_suffix {
something::key operator"" _key() { ... }
}

// user code
void some_function() {
    using namespace key_suffix;
    "caps lock"_key.doSomething();
}
person Krzysztof Kosiński    schedule 04.09.2012
comment
Я определенно согласен с № 1, но для № 2 с этим существуют проблемы (см. этот вопрос). Являются ли эти проблемы достаточно заметными в пространствах имен, отличных от std, чтобы заставить программистов не импортировать все это в свой файл cpp? - person chris; 04.09.2012
comment
Эти проблемы более вероятны, если вы импортируете более одного пространства имен. Чтобы избежать этого, просто импортируйте не более одного пространства имен в каждую область. Не существует 100% надежного способа предотвратить конфликты имен — кто-то всегда может повторно использовать одно и то же имя пространства имен для двух разных библиотек. К счастью, на исправление конфликта имен редко уходит много времени, так как серии простого текстового поиска и замены будет достаточно, чтобы 99% кода снова скомпилировалось. - person Krzysztof Kosiński; 04.09.2012
comment
Я бы сказал, что № 2 приемлем только в очень маленьких областях, и в этот момент он все равно может стать бесполезным. Я видел только проблемы, связанные с его использованием, и никаких преимуществ. - person juanchopanza; 04.09.2012
comment
Одна проблема, которую мы заметили, заключается в том, что C++11 перенял многие части библиотеки Boost. Внезапно у нас появилось много конфликтов имен. - person Bo Persson; 04.09.2012