Я легко привык к префиксам стандартных идентификаторов std::
вместо того, чтобы торчать в using namespace std;
, Тем не менее, я начал изучать C # и заметил, что добавлять все, что необходимо при использовании директив, очень нормально, то есть вы увидите:
using System;
Console.Write("foo");
вместо:
System.Console.Write("foo");
Очевидно, как я выяснил из вопроса C # по этой теме, это использование происходит из-за того, что отдельные системные пространства имен в C # намного, намного меньше, чем std
находится в C ++, и, следовательно, устраняет проблемы, связанные со столкновением имен, так как вероятность намного меньше (и вы можете просто найти-заменить его полностью определенным именем, если библиотека обновляется со столкновением имен), и устраняет проблемы, связанные с с появлением дерьма из опций Intellisense, поскольку пространства имен достаточно малы для обработки.
Тогда возникает вопрос: если это постоянные причины использования директив в C #, то же самое относится и к C ++? В целом допустимо ли применять это к меньшим сторонним пространствам имен, а также к вашим собственным меньшим пространствам имен?
Теперь я понимаю, что это может вызвать немного споров, я хочу воспользоваться этим моментом, чтобы спросить, что это не превращается в аргумент. Хороший ответ должен включать основу, то есть преимущества или недостатки, и то, как использовать один путь над другим действительно имеет большое значение.
Причина, по которой я спрашиваю это, состоит в том, чтобы прояснить проблему и, возможно, убрать понятие, что использование директив в C ++ должно быть плохой вещью. Конечно, более длинные имена пространств имен могут быть сокращены с псевдонимом пространства имен, если необходимо, и полностью квалифицированные имена все еще могут использоваться при необходимости, но иногда директива using значительно облегчает доступ к некоторым членам, таким как пользовательские литеральные операторы, которые, насколько мне известно, не имеют формы ADL, что означает, что вы должны либо использовать директиву using, либо вызывать метод оператора с помощью синтаксиса функции, что в первую очередь сводит на нет всю цель использования оператора.
Например, у меня было пространство имен (которое включает в себя структуру, представляющую клавиатуру, наряду с буквенным суффиксом в качестве читаемого альтернативного средства доступа:
"caps lock"_key.disable();
Проблема здесь в том, что если вы не вставили ранее using namespace Whatever;
или же using Whatever::operator"" _key;
код не скомпилируется, что является плохой новостью для пользователя.
Использование директив имеет очевидные проблемы, когда std
участвует или когда используется таким образом в заголовке, что они приносят нежелательные дополнения для пользователя этого заголовка, но оправданно ли использовать их для других пространств имен, когда они содержатся в меньшей области действия, чем то, что включает в себя заголовок? Сочетания клавиш, избавленные от необходимости вводить каждый квалификатор каждый раз, суммируются, и с сегодняшними возможностями Intellisense определить, к какому пространству имен принадлежит неквалифицированный идентификатор, так же просто, как навести курсор на него.
Я думаю, что правила использования объявлений в C ++ довольно просты:
РЕДАКТИРОВАТЬ: для проблемы _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();
}
Других решений пока нет …