3

Namespaces aren't declared and defined like most other things, but the namespace equivalent of a forward declaration would be:

namespace X {}  // empty body

Normally, you define a namespace by placing other declarations inside it. But is there a problem for which this "namespace forward declaration" is the easiest solution? Of what use is an empty namespace?

  • I have a specific situation for which I've found this useful. If no one answers with it in the next day or two, I'll post it. I'm very curious if there's any other situations. –  Sep 27 '10 at 21:04
  • Interesting question. +1 I can't think of a situation where this would be advantageous (though you could probably contrive a pathological example). I'm quite curious... – JoshD Sep 27 '10 at 21:05
  • Related: http://stackoverflow.com/questions/3673617/anonymous-namespace – James McNellis Sep 27 '10 at 21:12

2 Answers2

4

Here is one which even appears in the Standard: Declaring a using directive to denote a namespace

namespace unique { }
using namespace unique;

Afterwards you can open the namespace other times and add to it, and the using directive makes the stuff visible to the outer namespace.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • Where is that in the standard? –  Sep 27 '10 at 21:12
  • @Roger 7.3.1.1/1, unnamed namespaces – Johannes Schaub - litb Sep 27 '10 at 21:13
  • Ah, I've glossed over that so many times, I should've recognized it. I don't see where the empty namespace declaration is in the second—if it's lambda, what members are you going to define? –  Sep 27 '10 at 21:17
  • @Roger something like `flm::_1` or such. :) But I'm not sure about this use, so I'm going to remove it again. Because putting that namespace alias in the header is plain bad, and I only see limited use for such a thing in a .cpp file (if you are within `foo::lambda` currently you can just use unqualified names anyway). – Johannes Schaub - litb Sep 27 '10 at 21:24
  • My use is similar WRT using directives, but for a different purpose (and intended to be used in limited scopes, unlike the above). I think the only way this could be useful is with using directives; with no other context can you actually use the namespace. Or perhaps it could be used to "reserve" names if addition to a library's namespace wasn't (procedurally rather than formally) restricted? (That doesn't seem like a good idea.) –  Oct 01 '10 at 21:50
2

I use an empty namespace definition to simplify declarations for recursive functions, where one "side" is operator overloads. The operators are placed in their own namespace to allow selective use in scopes as desired, rather than forcing use if the header is included anywhere (and thus forcing errors if resolutions become ambiguous).

Example:

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::

The resolution of s << *begin is delayed until write_sequence is instantiated (because it involves template parameters), by which time the operator has been declared and can be found through the using directive. The call becomes recursive for nested containers:

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 has a similar output formatting library, but I don't know if they use the same implementation technique.