views:

137

answers:

2

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?

+5  A: 

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
Where is that in the standard?
Roger Pate
@Roger 7.3.1.1/1, unnamed namespaces
Johannes Schaub - litb
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?
Roger Pate
@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
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.)
Roger Pate
A: 

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.

Roger Pate