Когда необходимо пустое определение пространства имен?

Пространства имен не объявляются и не определяются, как большинство других вещей, но пространство имен, эквивалентное предварительному объявлению, будет таким:

namespace X {}  // empty body

Обычно вы определяете пространство имен, помещая в него другие объявления. Но есть ли проблема, для которой это «упреждающее объявление пространства имен» является самым простым решением? Какая польза от пустого пространства имен?


person Community    schedule 27.09.2010    source источник
comment
У меня есть конкретная ситуация, для которой я нашел это полезным. Если никто не ответит на него в ближайшие день или два, я опубликую его. Мне очень интересно, есть ли другие ситуации.   -  person    schedule 28.09.2010
comment
Интересный вопрос. +1 Я не могу придумать ситуацию, в которой это было бы выгодно (хотя вы, вероятно, могли бы придумать патологический пример). мне весьма любопытно...   -  person JoshD    schedule 28.09.2010
comment
Связано: stackoverflow.com/questions/3673617/anonymous-namespace   -  person James McNellis    schedule 28.09.2010


Ответы (2)


Вот один из них, который даже фигурирует в Стандарте: Объявление директивы using для обозначения пространства имен.

namespace unique { }
using namespace unique;

Впоследствии вы можете открыть пространство имен в другой раз и добавить к нему, а директива using делает материал видимым для внешнего пространства имен.

person Johannes Schaub - litb    schedule 27.09.2010
comment
Где это в стандарте? - person ; 28.09.2010
comment
@Roger 7.3.1.1/1, безымянные пространства имен - person Johannes Schaub - litb; 28.09.2010
comment
Ах, я столько раз умалчивал об этом, что должен был узнать. Я не вижу, где во втором находится объявление пустого пространства имен — если это лямбда, какие члены вы собираетесь определять? - person ; 28.09.2010
comment
@Roger что-то вроде flm::_1 или вроде того. :) Но я не уверен в этом использовании, поэтому я собираюсь удалить его снова. Потому что помещать этот псевдоним пространства имен в заголовок просто плохо, и я вижу только ограниченное использование такой вещи в файле .cpp (если вы в настоящее время находитесь в пределах foo::lambda, вы все равно можете просто использовать неполные имена). - person Johannes Schaub - litb; 28.09.2010
comment
Мое использование похоже на использование директив WRT, но для другой цели (и предназначено для использования в ограниченных областях, в отличие от вышеизложенного). Я думаю, что это может быть полезно только с использованием директив; без другого контекста вы действительно можете использовать пространство имен. Или, возможно, его можно использовать для резервирования имен, если добавление в пространство имен библиотеки не было (процедурно, а не формально) ограничено? (Это не кажется хорошей идеей.) - person ; 02.10.2010

Я использую определение пустого пространства имен, чтобы упростить объявления рекурсивных функций, где одна «сторона» — это перегрузки операторов. Операторы помещаются в свое собственное пространство имен, чтобы разрешить выборочное использование в желаемых областях, а не принудительно использовать, если заголовок включен где-либо (и, таким образом, вызывать ошибки, если разрешения становятся неоднозначными).

Пример:

namespace container_inserters {}

template<class Stream, class Iter, class Ch>
void write_sequence(Stream& s, Iter begin, Iter end,
                    Ch const *initial, Ch const *sep, Ch const *final)
{
  using namespace container_inserters;
  if (initial) s << initial;
  if (begin != end) {
    s << *begin;
    ++begin;
    for (; begin != end; ++begin) {
      if (sep) s << sep;
      s << *begin;
    }
  }
  if (final) s << final;
}

namespace container_inserters {
#define G(N) \
template<class Ch, class Tr, class T, class A> \
std::basic_ostream<Ch,Tr>& operator<<(std::basic_ostream<Ch,Tr> &s, \
                                      N<T,A> const &value) \
{ \
  write_sequence(s, value.begin(), value.end(), "[", ", ", "]"); \
  return s; \
}
G(std::deque)
G(std::list)
G(std::vector)
#undef G
}  // container_inserters::

Разрешение s << *begin откладывается до тех пор, пока не будет создан экземпляр write_sequence (поскольку он включает параметры шаблона), к этому моменту оператор уже объявлен и его можно найти с помощью директивы using. Вызов становится рекурсивным для вложенных контейнеров:

int main() {
  using namespace std;
  vector<deque<list<int> > > v (3, deque<list<int> >(2, list<int>(1, 42)));

  using namespace container_inserters;
  cout << v << '\n';

  return 0;
}
// output:
//  [[[42], [42]], [[42], [42]], [[42], [42]]]

У Boost есть похожая библиотека форматирования вывода, но я не знаю, используют ли они ту же технику реализации.

person Community    schedule 01.10.2010