Почему мы не можем объявить пространство имен внутри класса?

Объявление класса внутри класса допустимо. (Вложенные классы)

Объявление пространства имен внутри класса недопустимо.

Вопрос: есть ли веская причина (кроме проблем грамматики / синтаксиса в c ++) запретить объявление пространства имен в классе?

Что касается того, почему я хотел бы сделать это, вот пример:

Позволять'имеют базовую делькарацию контейнера двоичного дерева

template
class binary_tree
{
 public:
  ... stuff ....     

 private:
  ... iterators class declaration ...

 public:
  typedef left_depth_iterator_impl     left_depth_iterator;
  typedef right_depth_iterator_impl    right_depth_iterator;
  typedef left_breadth_iterator_impl   left_breadth_iterator;
  typedef right_breadth_iterator_impl  right_breadth_iterator;

  ... stuff ....     

 private:
  Data         data;
  binary_tree* left;
  binary_tree* right;
};

Теперь я заметил, что в моем классе много итераторов, поэтому я хотел бы перегруппировать их в одном и том же пространстве имен:

template
class binary_tree
{
 public:
  ... stuff ....     

 private:
  ... iterators class declaration ...

 public:
  namespace iterator
  {
    typedef left_depth_iterator_impl     left_depth;
    typedef right_depth_iterator_impl    right_depth;
    typedef left_breadth_iterator_impl   left_breadth;
    typedef right_breadth_iterator_impl  right_breadth;
  }

  ... stuff ....     

 private:
  Data         data;
  binary_tree* left;
  binary_tree* right;
};

Это позволило бы простое использование:

void  function()
{
  binary_tree::iterator::left_depth   it;

  ...stuff...
}

Это работает, если я использую класс вместо пространства имен, но затем я вынужден объявить класс, который никогда не будет создан, что является вполне пространством имен.

Зачем разрешать вложенные классы и запрещать вложенные пространства имен внутри классов? это наследственное бремя?

Будут оценены ответы с семантическими причинами, которые указывают не только часть стандарта (особенно части синтаксиса) :)

 Robert Cooper21 нояб. 2012 г., 01:19
Увидеть Эрика Липпертаответ наstackoverflow.com/questions/8671427/... Выдержки: функции не реализованы по умолчанию Отсутствие функции не нуждается в обосновании. Скорее, все функции должны быть обоснованы, показывая, что их преимущества перевешивают их затраты. Как человек, предлагающий эту функцию, вы обязаны объяснить, почему вы считаете эту функцию полезной; Я не обязан объяснять, почему это не так.
 WhozCraig21 нояб. 2012 г., 01:39
Ответ, на который ссылается Роберт, очень хорош для чтения, я хотел бы проголосовать за него еще несколько раз.
 neagoegab08 мар. 2013 г., 10:34
вы можете сделать ... #define inclass_namespace struct .. и вы можете использовать это так ...

Ответы на вопрос(5)

которую я чувствовал, заслуживает упоминания. Одно использование пространств имен внутри классов будет функциональным эквивалентом шаблонным пространствам имен.

template<class...types>
struct Namespace {
    namespace Implementation {
        ...
    }
};

// somewhere else

using namespace Namespace<types...>::Implementation;

// use templated stuff.
</types...></class...types>

Лично мне бы понравилась эта функция, но, кажется, спрос недостаточно высоко для его реализации.

 Svalorzen22 мар. 2019 г., 11:39
Это также было бы полезно для импорта вложенного типа enumЗначения в новой области.
 Anthony Monterrosa23 мар. 2019 г., 19:49
@ Svalorzen, да. Классы и пространства имен очень похожи, поэтому яЯ не уверен, почему так много против этой идеи.

ot;нет никакого реального преимущества. Иногда я'Я просто хотел бы отделить код без дополнительных последствий. Например, я работал в многопоточном модуле кольцевого буфера и хотел разделить элементы состояния, некоторые из которых являются атомарными и / или выровненными по памяти, на пространства имен для производителя и потребителя.

Просто называя всеproducer или жеconsumer префиксы (это моя текущая раздражающая реализация), ядобавляя загрязнение, которое затрудняет чтение кода. Например. когда все, что принадлежит производителю, начинается сproducer, Это'Вашему мозгу легче при чтении его случайно автозаменитьproducerProducerTimer (копия производителя таймера производителя) какproducerConsumerTimer (производитель тени потребительского таймера) илиconsumerProducerTimer (потребительская тень таймера производителя). Отладка, которая занимает больше времени, чем нужно, потому что код больше не может быть отсканирован.

Создавая вложенный класс / структуру:

Я мог бы дать следующему разработчику, который поддерживает этот код, идею о том, что более одного из них можно / нужно создавать, копировать и назначать друг другу в контексте, так что теперь вместо того, чтобы беспокоиться о присвоении имен, я также должен= delete эти вещи.Я мог бы добавить след памяти в контекст с помощью структурного выравнивания, которое в противном случае могло бы не потребоваться.Делать все члены статичными неt вариант, так как может быть создан более одного контекста, который будет нуждаться в собственных переменных состояния производителя / потребителя.Функции такой структуры больше не имеют доступа к другим данным или функциям-членам, таким как константы или функции, которые являются общими для обеих сторон, но вместо этого должны принимать эти вещи в качестве аргументов.

В идеале яЯ хотел бы иметь возможность изменить такие вещи:

rbptr producerPosition;
rbptr consumerPosition;

к этому:

namespace producer
{
    rbptr position;
}
namespace consumer
{
    rbptr position;
}

Тогда функции, которые должны касаться только членов-потребителей, могут использовать пространство имен потребителя, функции, которые должны касаться только членов-производителей, могут использовать пространство имен производителя, а функции, которые должны касаться обоих, должны явно их квалифицировать. Там'не было бы способа случайно коснуться переменной-потребителя в функции, которая 'только с использованием пространства имен производителя.

В этом случае стремление сводится исключительно к уменьшению коллизий именования между производителями и потребителями, и для сокращения пространств имен существуют пространства имен. По этой причине я поддерживаю предложение о возможности объявления пространств имен внутри классов.

 firda09 окт. 2018 г., 13:58
Добавить получить &установить операторы (приведение + назначение) и у вас естьсвойства (бесплатно - еще одна особенность пространства имен внутри класса / структуры).
 Drax17 июл. 2017 г., 10:31
Я разделяю это мнение, помеченный ответ помечается как принятый, потому что он отвечает на вопрос "почему это не так в настоящее время " на что главный ответ "Вы можете сделать это плохо с другой функцией, так что никто еще не предложил это "это неЯ имею в виду, что оно должно остаться таким, и я бы также поддержал такое предложение, день, когда кто-то сделает это :)

что пространства имен существуют ближе к верхнему уровню кода, поэтому две разные компании (или базы кода) могут смешивать код друг с другом. На более микроуровне я пишу с помощью IMAP для доступа к электронной почте и SMTP для отправки электронной почты и (может, я сильно упрощаю) иметь классы в любом из модулей, называемыхEmail это совсем другое дело, но у меня могло бы быть приложение, скажем, почтовый клиент, которое хочет использовать оба из одного класса, например возможно, он пересылает письма с одного аккаунта на другой. Пространства имен / имена пакетов / и т.д. позволяют это.

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

какие части стандартного расположения пространства имен мандата, мы подумаем сначала:

C ++ 11 7.3-p4: Каждое определение пространства имен должно появляться в глобальной области или в области пространства имен (3.3.6).

Что касается определений классов и предложения об объявлении пространства имен внутри, я приведу вас к ...

C ++ 11 9.2-p2: Класс считается полностью определенным типом объекта (3.9) (или завершенным типом) при закрытии} спецификатора класса. В спецификации членов класса класс рассматривается как завершенный в теле функций, аргументах по умолчанию, спецификациях исключений и инициализаторах фигурных или равных скобок для нестатических членов данных (включая такие вещи во вложенных классах). В противном случае он рассматривается как неполный в своей собственной спецификации членов класса.

Ergo, определение класса является конечным, когда достигнуто закрывающее фигурное выражение. Его нельзя открыть обратно и расширить (деривация - это нечто иное, но она НЕ расширяетсятолько что определенный класс).

Но в самом начале стандартного определения пространства имен скрывается возможность его расширения; расширить его из-за отсутствия лучшего термина:

C ++ 7.3-p1: Пространство имен является произвольно названным декларативным регионом. Имя пространства имен может использоваться для доступа к объектам, объявленным в этом пространстве имен; то есть члены пространства имен.В отличие от других декларативных областей, определение пространства имен может быть разбито на несколько частей одной или нескольких единиц перевода. (выделение добавлено).

Следовательно, пространство имен внутри класса будет нарушать определение в 7.3-p4. Предполагая, что этого не было, это было бывозможный объявлять пространство имен где угодно, в том числе в классе, но поскольку определение класса формализуется после его закрытия, у вас останется только возможность делать следующее, если вы будете поддерживать соответствие 7.3-p1:

class Foo
{
   namespace bar
   {
       ..stuff..
   }

   .. more stuff ..

   namespace bar
   {
       ..still more stuff..
   }
};

Полезность этогоособенность вероятно, обсуждался в течение 3-х полных секунд, прежде чем был установлен 7.3-p4 для его урегулирования.

 Antonio13 июн. 2016 г., 11:02
Therefore, a namespace within a class would violate the definition in 7.3-p4.  Ты имел ввиду ?[...] in 7.3-p1
 einpoklum17 нояб. 2016 г., 12:47
Хорошо, что'Это чистая техничность. Вы можете добавить исключение к предложению расширяемости, говоря, что только пространства имен за пределами области действия класса могут быть расширены. Легко peasy.I '
Решение Вопроса

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

Что бы купить пространство имен внутри классов? Вы бы действительно сказалиbinary_tree::iterator::left_depth вместо простоbinary_tree::left_depth? Возможно, если у вас было несколько пространств имен внутри, вы используете их, чтобы различать, скажем,binary_tree::depth_iterator::left а также .binary_tree::breadth_iterator::right

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

 kushy18 авг. 2017 г., 10:39
Было бы полезно, когда вы неЯ не хочу смешивать переменные с похожими именами (потому что они делают схожие вещи, но в разных местах кода). Конечно, всегда есть разные способы достичь этого, но пространства имен внутри классов будут простым решением, когда вы нене хочу использовать дополнительные структуры для этого.
 idij20 янв. 2015 г., 12:57
Это'было бы полезно для шаблонов, где класс использует что-то внутри пространства имен какего" версия чего-то. например T :: Пространство имен :: EnumValue
 Brian Gordon10 февр. 2014 г., 22:33
Особенности обычно нене может быть добавлено, если нетспрос ". Мыявляются говорить о C ++, верно?
 einpoklum17 нояб. 2016 г., 12:45
Пространства имен являются (почти) полностью синтаксическим сахаром внутри и снаружи классов. Так зачем вообще их?

Ваш ответ на вопрос