Когда нужно определение пустого пространства имен? - PullRequest
3 голосов
/ 28 сентября 2010

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

namespace X {}  // empty body

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

Ответы [ 2 ]

4 голосов
/ 28 сентября 2010

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

namespace unique { }
using namespace unique;

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

2 голосов
/ 02 октября 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 имеет похожую библиотеку форматирования вывода, но я не знаю, используют ли они одну и ту же технику реализации.

...