Подтвердить что ты не робот

С++ namespace - лучшая практика дилеммы

Я нахожу, что то, что я считал "лучшей практикой" для использования пространства имен в С++, вредит читабельности моего кода и заставляет меня задаться вопросом, как их использовать.

Моя программа состоит из нескольких различных модулей, которые в основном встроены в библиотеки, которые использует "основное" приложение. Каждая библиотека использует свое собственное пространство имен, а их пространства имен являются "внутренними" пространствами имен проектов, чтобы помочь проекту против конфликтов имен с сторонним кодом. Поэтому я заканчиваю именами классов, такими как "myproject:: logging:: Logger" и "myproject:: reporting:: ReportType" (как составленные примеры).

Пока все хорошо. И в моих .cpp файлах у меня нет проблем. Например, я использую "using myproject:: logging" наверху и могу чисто ссылаться на мой класс Logging. В маловероятном случае конфликта между двумя моими пространствами имен я могу просто сказать, какой из них я хочу. Это хорошо работает.

Файлы заголовков разные. Он считал, что неправильная практика заключается в том, чтобы использовать операторы в заголовках, поскольку они будут влиять на несвязанный код, который их не ожидает. Поэтому я всегда полностью квалифицирую все имена в файлах .hpp. Это было несколько уродливо, но управляемо до сих пор, поэтому я смирился с этим. Но теперь я увеличиваю использование кода шаблона в своих библиотеках, а это значит, что в моих .hpp файлах есть гораздо более актуальный код. И, чтобы полностью квалифицировать каждое имя, он делает код практически нечитаемым из-за длины имен типов.

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

Альтернативой является использование коротких одноэлементных пространств имен, поэтому вместо "myproject:: logging:: Logger" я бы просто имел "log:: Logger", который бы очень помог, но вероятность того, что конфликты пространства имен значительно выше, а также пространства имен передают менее полезную информацию.

Как я уже сказал, это действительно влияет на код в .hpp файлах, так как я с радостью использую "использование пространства имен" в своих файлах реализации, чтобы сделать это управляемым, но это становится проблемой, поскольку я смотрю на свой шаблонный код в .hpp файлах и подумайте "eww....", что не может быть хорошим: P

Кто-нибудь получил практические советы?

4b9b3361

Ответ 1

Я был в этой ситуации раньше. Часто бывает, что многие функции/классы шаблонов в ваших заголовках действительно являются "реализацией", хотя по характеру шаблонов на С++ вы вынуждены помещать их в заголовочный файл. Таким образом, я просто поместил все в какое-то "пространство деталей" или "реализацию", где я могу с комфортом использовать "использование пространства имен". В конце я "бросаю" то, что люди должны использовать в соответствующем месте. Вот так:

namespace myproject { namespace somemodule {

namespace _implementation {

using namespace myproject::othermodule;
using namespace myproject::yetanothermodule;

template <...>
class some_internal_metafunction{
...
};

template <...>
class stuff_people_should_use_outside {
...
};

} // namespace implementation       

using stuff_people_should_use_outside ;
}} // namespace myproject::somemodule

Этот подход может немного увеличить имена в ваших отчетах компилятора.

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

Ответ 2

Вот что я делаю.

В <mylibrary.h>:

namespace myproject {
  namespace mylibrary
  {
    namespace impl
    {
      using namespace otherlibrary;
      using namespace boost;
      using namespace std;
      using namespace whatever::floats::your::boat;

      class myclass;
      class myotherclass;
    };
    using impl::myclass;
    using impl::myotherclass;
  };
};

В источнике:

#include <mylibrary.h>
using namespace myproject::mylibrary; //clean!

Ответ 3

Лично? Я бы избавился от части "myproject". Какая вероятность, что ваша библиотека будет использовать то же имя пространства имен, что и другое, и иметь символ, определенный с тем же именем, что и другой?

Кроме того, я бы предложил более короткие имена для пространств имен, которые вы ожидаете использовать в заголовках.

Ответ 4

Мой опыт заключался в том, что гораздо удобнее иметь одно пространство имен для всего вашего кода по причинам, упомянутым в вашем исходном сообщении. Это пространство имен защищает ваши идентификаторы от столкновения с идентификаторами сторонних библиотек. Ваше пространство имен - ваше доминирование, и легко сохранить его без конфликтов.

Ответ 5

Если ваш проект не очень-очень большой (я имею в виду, очень огромный), использование только myproject должно быть достаточным. Если вы действительно хотите разделить проект на части, вы можете использовать более обобщенные пространства имен. Например, если бы я строил игровой движок, я бы пошел на пространства имен, такие как MyEngine:: Core, MyEngine:: Renderer, MyEngine:: Input, MyEngine:: Sound и т.д.