Посмотрите, как организована стандартная библиотека (или boost).Почти все это находится внутри единого пространства имен std
.Поместить все в свое собственное пространство имен очень мало.
Boost помещает большинство вещей в boost
, в то время как major библиотеки получают одно подпространство имен (boost::mpl
или boost::filesystem
, например).И библиотеки обычно определяют единственное подпространство имен aux
для внутренних деталей реализации.
Но вы обычно не видите глубоких или детальных иерархий пространства имен, потому что с ними просто больно работать, и мало что нужноот них никакой пользы.
Вот несколько полезных правил:
Вспомогательные функции, связанные с конкретным классом, должны находиться в том же пространстве имен, что и класс, чтобы позволить ADL работать.Тогда вам вообще не нужно уточнять имя вспомогательной функции при ее вызове.(Например, как вы можете вызывать sort
вместо std::sort
на итераторах, определенных в std
).
Для всего остального, помните, что целью пространств имен является предотвращение столкновений имен и ничего больше.Таким образом, вся ваша библиотека должна находиться в пространстве имен a , чтобы избежать конфликтов с пользовательским кодом, но в этом пространстве имен нет технической необходимости в дополнительных подпространствах имен, если только вы не планируете вводить конфликтующие имена.
ВыВозможно, вы захотите разделить внутреннюю часть вашей библиотеки в подпространстве имен, чтобы пользователи случайно не забрали их из основного пространства имен, как в Boost aux
.
Но, как правило, я бы предложил всего несколькокак можно больше вложенных пространств имен.
И, наконец, я стремлюсь использовать короткие, удобные для ввода и легко читаемые имена для своих пространств имен (опять же, std
- хороший примерСледуйте. Коротко и по существу, и почти всегда без дальнейших вложенных пространств имен, так что вам не будет скучно от необходимости часто писать его, и поэтому он не будет слишком загромождать ваш исходный код.)
Только первое правило о вспомогательных функциях и ADL позволило бы переписать ваш пример следующим образом:
MyLibrary::MyContainer<int> Numbers = Insert(OtherContainer, 123, 456);
Тогда мы могли бы переименовать MyLibrary
, скажем, Lib
:
Lib::MyContainer<int> Numbers = Insert(OtherContainer, 123, 456);
и вы готовы к чему-то довольно управляемому.
Не должно быть никаких столкновений между похожими служебными функциями для разных классов.C ++ позволяет вам перегружать функции и специализировать шаблоны, так что вы можете иметь как Insert(ContainerA)
, так и Insert(ContainerB)
в одном и том же пространстве имен.
И, конечно, столкновения между пространствами имен и классами возможны, только если вына самом деле имеют дополнительные вложенные пространства имен.
Помните, что в вашем Library
пространстве имен только вы диктует, какие имена вводить.И поэтому вы можете избежать столкновений имен, просто не создавая никаких конфликтующих имен.Пространство имен для отделения кода пользователя от кода библиотеки важно, потому что они могут не знать друг о друге, и поэтому столкновения могут произойти непреднамеренно.
Но в вашей библиотеке вы можете просто дать всем не конфликтующие имена.