Я переключился с C ++ на Java и C # и думаю, что использование пространств имен / пакетов там намного лучше (хорошо структурировано). Затем я вернулся к C ++ и попытался использовать пространства имен таким же образом, но требуемый синтаксис в заголовочном файле ужасен.
namespace MyCompany
{
namespace MyModule
{
namespace MyModulePart //e.g. Input
{
namespace MySubModulePart
{
namespace ...
{
public class MyClass
Мне тоже кажется странным следующее (чтобы избежать глубокого отступа):
namespace MyCompany
{
namespace MyModule
{
namespace MyModulePart //e.g. Input
{
namespace MySubModulePart
{
namespace ...
{
public class MyClass
{
Есть ли более короткий способ выразить вышесказанное? Я упускаю что-то вроде
namespace MyCompany::MyModule::MyModulePart::...
{
public class MyClass
Обновить
Хорошо, некоторые говорят, что концепция использования в Java / C # и C ++ отличается. В самом деле? Я думаю, что (динамическая) загрузка классов - не единственная цель пространств имен (это очень технически обоснованная перспектива). Почему бы мне не использовать его для удобства чтения и структурирования, например, подумайте о «IntelliSense».
В настоящее время нет никакой логики / связи между пространством имен и тем, что вы можете там найти. Java и C # делают это намного лучше ... Зачем включать <iostream>
и иметь пространство имен std
? Хорошо, если вы говорите, что логика должна полагаться на заголовок для включения, почему #include не использует удобный для IntelliSense синтаксис, например #include <std::io::stream>
или <std/io/stream>
? Я думаю, что отсутствующая структуризация в библиотеках по умолчанию - это слабое место C ++ по сравнению с Java / C #.
Если уникальность острых конфликтов составляет один балл (что также относится к C # и Java), хорошей идеей будет использовать имя проекта или название компании в качестве пространства имен, вам так не кажется?
С одной стороны, сказано, что C ++ - самый гибкий ... но все сказали: «Не делай этого»? Мне кажется, C ++ может многое делать, но во многих случаях у него ужасный синтаксис даже для самых простых вещей по сравнению с C #.
Обновление 2
Большинство пользователей считают бессмысленным создавать более глубокую вложенность, чем два уровня. Хорошо, а как насчет пространств имен Windows :: UI :: Xaml и Windows :: UI :: Xaml :: Controls :: Primitives в разработке под Win8? Я думаю, что использование пространств имен Microsoft имеет смысл и действительно глубже, чем просто 2 уровня. Я думаю, что более крупные библиотеки / проекты нуждаются в более глубоком вложении (я ненавижу такие имена классов, как ExtraLongClassNameBecauseEveryThingIsInTheSameNameSpace ... тогда вы также можете поместить все в глобальное пространство имен.)
Обновление 3 - Заключение
Большинство говорит «не делай этого», но ... даже boost имеет более глубокую вложенность, чем один или два уровня. Да, это библиотека, но: Если вам нужен код многократного использования - относитесь к своему собственному коду, как к библиотеке, которую вы отдадите кому-то другому. Я также использую более глубокое вложение для целей обнаружения с использованием пространств имен.
источник
namespace
ключевым словом?Ответы:
C ++ 17 может упростить определение вложенного пространства имен:
эквивалентно
См. (8) на странице пространства имен в cppreference:
http://en.cppreference.com/w/cpp/language/namespace
источник
/std:c++latest
/std:c++latest
Visual Studio 2015, а также Boost, вы можете столкнуться с очень мистическими ошибками компилятора при включении некоторых заголовков Boost. Я столкнулся с этой проблемой, как описано в этом вопросе StackOverflowЧтобы избежать очень глубоких отступов, я обычно делаю это так:
источник
clang-format
не может отформатировать это, поскольку вы показываете clang.llvm.org/docs/ClangFormatStyleOptions.html (NamespaceIndentation)Я полностью поддерживаю ответ Петерхена, но хочу добавить что-то, что касается другой части вашего вопроса.
Объявление пространств имен - один из очень редких случаев в C ++, когда мне действительно нравится использование
#define
s.Это также устраняет необходимость в комментариях рядом с закрывающей фигурной скобкой пространства имен (вы когда-нибудь прокручивали вниз большой исходный файл и пытались добавить / удалить / сбалансировать фигурные скобки, в которых отсутствовали комментарии о том, какая скобка какую область закрывает? Не весело? .).
Если вы хотите поместить все объявления пространств имен в одну строку, вы также можете сделать это с помощью небольшой (довольно уродливой) магии препроцессора:
Теперь вы можете это сделать:
Для вложения глубже трех уровней вам нужно будет добавить вспомогательные макросы до желаемого количества.
источник
#define
бы мне ни не нравилась эта магия препроцессора, меня очень впечатлила ... только если мне не нужно будет добавлять дополнительные вспомогательные макросы для более глубокого вложения ... ну, я все равно не собираюсь его использовать, так что .. .Пространства имен C ++ используются для группировки интерфейсов, а не для разделения компонентов или выражения политического разделения.
Стандарт старается изо всех сил запрещать использование пространств имен в стиле Java. Например, псевдонимы пространств имен позволяют легко использовать глубоко вложенные или длинные имена пространств имен.
Но
namespace nsc {}
тогда это будет ошибкой, потому что пространство имен может быть определено только с использованием его имени- исходного-пространства-имен . По сути, стандарт упрощает задачу пользователя такой библиотеки, но затрудняет ее реализацию . Это отговаривает людей писать такие вещи, но смягчает последствия, если они это сделают.У вас должно быть одно пространство имен для каждого интерфейса, определяемого набором связанных классов и функций. Внутренние или дополнительные подчиненные интерфейсы могут входить во вложенные пространства имен. Но глубина более двух уровней должна быть очень серьезным сигналом тревоги.
Рассмотрите возможность использования символов подчеркивания и префиксов идентификаторов там, где
::
оператор не нужен.источник
company::division
надcompany_division
?Нет, и, пожалуйста, не делай этого.
Назначение пространств имен в первую очередь - разрешение конфликтов в глобальном пространстве имен.
Второстепенное назначение - местное сокращение символов; например, сложный
UpdateUI
метод может использовать болееusing namespace WndUI
короткие символы.Я работаю над проектом 1.3MLoc, и единственные пространства имен, которые у нас есть:
#import
и#include windows.h
)ModuleDetailHereBeTygers
пространства имен в библиотеках, содержащих только заголовки)В этом проекте в именах классов и т. Д. Используется двух- или трехбуквенный «региональный» код (например,
CDBNode
вместоDB::CNode
). Если вы предпочитаете последнее, есть место для второго уровня «общедоступных» пространств имен, но не более того.Перечисления для конкретных классов и т. Д. Могут быть членами этих классов (хотя я согласен, что это не всегда хорошо, и иногда трудно сказать, следует ли вам)
Пространство имен «компания» также редко требуется, за исключением случаев, когда у вас возникают большие проблемы со сторонними библиотеками, которые распространяются как двоичные, не предоставляют собственное пространство имен и не могут быть легко помещены в одно (например, в двоичном распространение). Тем не менее, по моему опыту, принудительно поместить их в пространство имен сделать гораздо проще.
[править] Согласно последующему вопросу Стеги:
Извините, если я недостаточно ясно понял: два уровня - это не жесткое ограничение, а большее - по сути не плохо. Я просто хотел указать, что вам редко нужно больше двух, по моему опыту, даже для большой базы кода. Более глубокое или более мелкое вложение - это компромисс.
Теперь, возможно, дело Microsoft обстоит иначе. Предположительно гораздо большая команда, и весь код - это библиотека.
Я предполагаю, что Microsoft имитирует здесь успех библиотеки .NET, где пространства имен способствуют обнаружению обширной библиотеки. (В .NET около 18000 типов.)
Далее я предполагаю, что в пространстве имен есть оптимальные (по порядку величины) символы. скажем, 1 не имеет смысла, 100 звучит правильно, 10000 явно слишком много.
TL; DR: Это компромисс, и у нас нет точных цифр. Играйте осторожно, не переусердствуйте в любом направлении. «Не делай этого» исходит просто из «У вас проблемы с этим, у меня будут проблемы с этим, и я не вижу причины, по которой вам это может понадобиться».
источник
Constants
, а затем создавать вложенные пространства имен с соответствующими именами для классификации констант; при необходимости я использую дополнительные пространства имен для предотвращения конфликтов имен. ЭтоConstants
пространство имен само содержится в универсальном пространстве имен для системного кода программы с таким именем, какSysData
. Это создает полное имя , содержащее три или четыре пространства имен (например,SysData::Constants::ErrorMessages
,SysData::Constants::Ailments::Bitflags
илиSysData::Defaults::Engine::TextSystem
).using
директиву для ввода соответствующих имен, сводя к минимуму возможность конфликта имен. Я считаю, что это улучшает читаемость и помогает документировать зависимости любого блока кода. Помимо констант, я стараюсь, если возможно, использовать два пространства имен (например,SysData::Exceptions
иSysData::Classes
).Вот цитата из документов Lzz (Lazy C ++):
Конечно, качество источников, которое зависит от таких инструментов, является спорным ... Я бы сказал, что это скорее любопытство, показывающее, что синтаксическая болезнь, вызванная C ++, может принимать разные формы (у меня тоже есть ...)
источник
Оба стандарта (C ++ 2003 и C ++ 11) очень четко указывают, что имя пространства имен является идентификатором. Это означает, что требуются явные вложенные заголовки.
У меня сложилось впечатление, что не составляет большого труда разрешить размещение квалифицированного идентификатора помимо простого имени пространства имен, но по какой-то причине это запрещено.
источник
В этом документе достаточно хорошо освещена тема: Документ о пространстве имен
Что в основном сводится к следующему. Чем длиннее ваши пространства имен, тем больше вероятность, что люди будут использовать
using namespace
директиву.Итак, глядя на следующий код, вы можете увидеть пример, в котором вам будет больно:
Этот код будет компилироваться нормально, однако, если вы раскомментируете строку,
//using namespace def;
тогда пространство имен «testing» станет неоднозначным, и возникнут конфликты имен. Это означает, что ваша кодовая база может перейти от стабильной к нестабильной за счет включения сторонней библиотеки.В C #, даже если вы должны использовать,
using abc;
иusing def;
компилятор может распознать этоtesting::myClass
или даже простоmyClass
находится только вabc::testing
пространстве имен, но C ++ не распознает это, и это обнаруживается как коллизия.источник
Да, тебе придется делать это как
Однако вы пытаетесь использовать пространства имен так, как они не должны использоваться. Проверьте этот вопрос, может быть, он вам пригодится.
источник
Вы можете использовать этот синтаксис:
Обратите внимание, что этот синтаксис действителен даже в C ++ 98 и почти аналогичен синтаксису, который теперь доступен в C ++ 17 с определениями вложенных пространств имен .
Удачного раскроя!
Источники:
источник
[РЕДАКТИРОВАТЬ:]
Поскольку в C ++ 17 вложенные пространства имен поддерживаются как стандартная языковая функция ( https://en.wikipedia.org/wiki/C%2B%2B17 ). На данный момент эта функция не поддерживается в g ++ 8, но ее можно найти в компиляторе clang ++ 6.0.
[ВЫВОД:]
Используйте в
clang++6.0 -std=c++17
качестве команды компиляции по умолчанию. Тогда все должно работать нормально - и вы сможете компилироватьnamespace OuterNS::InnerNS1::InnerNS2 { ... }
в своих файлах.[ОРИГИНАЛЬНЫЙ ОТВЕТ:]
Поскольку этот вопрос немного устарел, я предполагаю, что вы ушли. Но для тех, кто все еще ищет ответ, я пришел к следующей идее:
(Могу я сделать здесь рекламу Emacs :)?) Публикация изображения намного проще и читабельнее, чем просто публикация кода. Я не собираюсь давать исчерпывающий ответ по всем угловым случаям, просто я хотел вдохновить. (Я полностью поддерживаю C # и считаю, что во многих случаях C ++ должен использовать некоторые функции ООП, поскольку C # популярен в основном благодаря сравнительной простоте использования).
источник