Пространство имен C ++ - передовая практика - PullRequest
24 голосов
/ 05 августа 2011

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

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

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

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

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

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

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

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

Ответы [ 6 ]

20 голосов
/ 05 августа 2011

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

В <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!
18 голосов
/ 05 августа 2011

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

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

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

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

5 голосов
/ 05 августа 2011

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

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

2 голосов
/ 05 августа 2011

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

0 голосов
/ 25 августа 2018

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

// mylibrary.h
namespace myproject {
  namespace mylibrary {
    namespace impl {

      using namespace std;

      namespace stripped_std {

        // Here goes normal structure of your program:
        // classes, nested namespaces etc.
        class myclass;
        namespace my_inner_namespace {
                ...     
        }

       } // namespace stripped_std   
    } // namespace impl

  using namespace impl::stripped_std;

  } // namespace mylibrary
} namespace myproject


// Usage in .cpp file
#include <mylibrary.h>
using namespace myproject::mylibrary;

Это похоже на то, что было предложено n.m., но с модификацией: есть еще одно вспомогательное пространство имен stripped_std. Общий эффект заключается в том, что строка using namespace myproject::mylibrary; позволяет вам ссылаться на внутреннюю структуру пространства имен, и в то же время она не переносит namespace std в область действия пользователя библиотеки.


Жаль, что следующий синтаксис

using namespace std {
...
}

недопустим в C ++ на момент написания этого поста.

0 голосов
/ 05 августа 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...