При написании библиотеки на C++ многие сталкиваются с определенными трудностями при написании и организации кода. У некоторых уже есть готовые решения, у других их нет и они пытаются найти эти решения. Некоторые трудности при написании кода библиотеки, в большей степени касающиеся «самодокументирования», можно решить с помощью «рабочих» пространств имен.
Для начала, опишем эти трудности и представим обычные способы решения.
Предположим, что библиотека реализует некоторую сущность some_class, которую она предоставляет пользователю библиотеки. Определение some_class зависит от другой сущности библиотеки detail_class, которая является частью реализации и пользователю не предоставляется. Библиотека поставляется только в виде заголовочных файлов.
Распределение кода по файлам в данном топике не рассматривается.
Стандартное решение 1
namespace lib_namespace { class detail_class { }; class some_class { public: // открытый интерфейс private: detail_class a_; // другие члены класса }; }
Плюс данного решения:
1) минимальное количество кода, необходимого для его реализации.
Минусы:
1) Плохое «самодокументирование» кода. Не всегда по имени классов реализации в данном случае можно определить пользовательские они или нет.
2) Захламление пространства имен библиотеки. Некоторые среды разработки при использовании данного пространства имен, будут отображать то, что пользователю библиотеки не нужно:

Стандартное решение 2
namespace lib_namespace { namespace impl { class detail_class { }; }} namespace lib_namespace { class some_class { public: // открытый интерфейс private: impl::detail_class a_; // другие члены класса }; }
Данное решение полностью убирает недостатки предыдущего подхода, но добавляет свои:
1) введение дополнительного пространства имен;
2) В любом библиотечном классе, предоставляемом пользователю и размещенном в lib_namespace, необходимо для всех элементов реализации указывать префикс impl::.
Достоинства:
1) хорошее «самодокументирование» кода.
Решение на основе «рабочих» пространств имен
namespace work_lib_namespace { class detail_class { }; class some_class { public: // открытый интерфейс private: detail_class a_; // другие члены класса }; } namespace lib_namespace { using ::work_lib_namespace::some_class; }
Весь код библиотеки размещается в рабочем пространстве имен work_lib_namespace. Все сущности, которые библиотека предоставляет пользователю, добавляются в основное пространство имен библиотеки посредством using.
Недостаток данного подхода:
1) введение дополнительного пространства имен.
Достоинства:
1) «самодокументирование» кода;
2) возможность использования using namespace some_ns внутри рабочего пространства имен (даже в тех заголовочных файлах библиотеки, которые пользователь непосредственно подключает):
namespace work_lib_namespace { using namespace std; class detail_class { public: // интерфейс private: vector<int> data_; }; }
Заключение
Представленный способ организации библиотеки позволяет с одной стороны добиться хорошего «самодокументирования» кода, а с другой — позволить разработчикам библиотеки использовать using namespace не только в файлах реализации сpp, но и в заголовочных файлах.
