views:

257

answers:

4

The standard does not allow code like this:

namespace Hello::World {

//Things that are in namespace Hello::World

}

and instead requires

namespace Hello { namespace World {

//Things that are in namespace Hello::World

}}

What is the rationale? Was this simply not thought of at the time, or is there a specific reason it is not included?

It seems that the first syntax more directly expresses in which namespace one is supposed to be, as the declaration mimics the actual use of the namespace in later code. It also results in less indentation if you are unfortunate enough to be using a "dumb" bracket counting indentation tool.

+12  A: 

The reason is most likely "because that's how the language evolved."

There has been at least one proposal ("Nested Namespace Definition Proposal" in 2003) to allow nested namespace definitions, but it was not selected for inclusion in C++0x.

James McNellis
+1 for pointing at the proposal -- I was not aware of that.
Billy ONeal
After reviewing that proposal and thinking on it a bit, I think you're almost certainly right. I bet it wasn't selected just because the proposed benefit didn't seem worth the hassle of getting a proposal through the standardization process.
Omnifarious
Accepting the answer with the highest number of upvotes because I obviously cannot divine the true answer here.
Billy ONeal
+2  A: 

As I said in that "possible duplicate" thread, in C++ qualified names are reserved for referring to previously declared entities. This applies to both "sources" of qualified names: classes and namespaces.

AndreyT
@AndreyT: "Exact Duplicate" means, "This question is an exact duplicate of another question", not "There is an answer which applies to both questions." But +1 to this answer.
Billy ONeal
I don't think this sufficiently explains it. You can previously declare the namespace, but you still can't use this construct.
Johannes Schaub - litb
So, are you for the proposal or against it? I think Billy intended that the namespace was previously declared…
Potatoswatter
@Potatoswatter: Actually, I don't see why it makes a difference in either case.
Billy ONeal
+4  A: 

I presume you'd rather want it to be so that, given namespace X::Y, it should be equivalent to "namespace X { namespace Y`. Which sounds fine on the surface of it, but consider a corner case:

namespace Hello {
   namespace {
      namespace World {}
   }
}

// Does this refer to an existing namespace? Or does it define a new one?
namespace Hello::World {}
Pavel Minaev
+1 for pointing out something I didn't even know was legal :)
Billy ONeal
That would be a different namespace. `namespace Hello::World { }` would just be shorthand for `namespace Hello { namespace World { } }`, which is already allowed by the language.
James McNellis
@James - So basically there is no way to reference anonymous namespaces with the nested syntax? That seems reasonable to me since there really is no way to directly refer to an anonymous namespace any other way.
Omnifarious
@Omnifarious: I suppose you could use `namespace Hello::::World { }`, but I doubt anyone would support that :-P
James McNellis
@Billy ONeal: It is NOT legal. Even though in this case `Hello::World` refers to a previously declared namespace, language does not allow using such name for extending an existing namespace.
AndreyT
@AndreyT: I meant having a namespace inside of an anonymous namespace.
Billy ONeal
@James: that would be inconsistent with existing rules with respect to other identifiers. E.g. if, in my example, the anonymous namespace would also contain a definition of class `Foo`, then `Hello::Foo` would refer to it. It's not clear why namespaces should behave differently, especially when that difference is also silent (i.e. no diagnostics, just quietly create a new namespace).
Pavel Minaev
@Pavel - So perhaps the declaration should be considered ambiguous? What happens if you refer to a symbol that's defined both in the current namespace and an anonymous one?
Omnifarious
@Pavel: Not really. An unnamed namespace acts as if it were declared with a unique name and then a using directive were used to bring the names from that uniquely named namespace into the enclosing namespace. So, in your specific example, in `namespace Hello::World { }` (or `namespace Hello { namespace World { } }`) would create a new `World` namespace nested inside `Hello` that would hide the `World` namespace nested inside the unnamed namespace. I agree that the behavior might be confusing to some, but if so it's already confusing. Shorthand definitions wouldn't add to the confusion.
James McNellis
+1 for a feature I'd completely forgotten… and fooling around, I discovered a Comeau bug: add a class `World` in namespace `Hello` and Comeau incorrectly rejects the using declaration!
Potatoswatter
@Potato: Do you have a code snippet for that? I can't figure out how to reproduce that.
James McNellis
@James: Oops, there isn't a using declaration in Pavel's code. Try `namespace Y {class X {};namespace { namespace X {}}}using namespace Y::X;namespace Z = Y::X;`
Potatoswatter
@Potato: That error is expected though: the class named `X` in namespace `Y` hides the namespace named `X` introduced by the `using namespace <unique>;` from the unnamed namespace definition. This behavior is defined in §3.3.7/4: "During the lookup of a name qualified by a namespace name, declarations that would otherwise be made visible by a _using-directive_ can be hidden by declarations with the same name in the namespace containing the _using-directive."_
James McNellis
@James: There's a special case in §3.4.6: "When looking up a namespace-name in a using-directive or namespace-alias-definition, only namespace names are considered." - hence my specific examples.
Potatoswatter
@Potato: Hmmmmmmm. So, if _only namespace names are considered,_ does that mean that other names cannot hide namespace names at all during name lookup in a _using-directive?_ That sounds plausible. I think I have to read through §3.4 and §7.3.4 again...
James McNellis
@James: However, these directives may appear in local scope, so the only intent may have been that local names don't hide namespaces. Hard to tell. Comeau accepts my snippet if the outermost namespace{} is removed, though, which is inconsistent.
Potatoswatter
@Potato: This is an excellent example of why I love C++. :-O
James McNellis
@Potato: That text (§3.4.6) was changed in the latest draft (N3126). It now reads: "In a using-directive or namespace-alias-definition, during the lookup for a namespace-name or for a name in a nested-name-specifier only namespace names are considered." I'm not sure yet whether that's any clearer.
James McNellis
@James: I think they broadened it as a correction because `Y::X` isn't a namespace-name, it's a nested-name-specifier. Only `Y` and `X` are namespace-names. So if anything, I was possibly wrong before (well, a nested-name-specifier naming a namespace still contains several namespace-names, right?) but now it's definite on the issue.
Potatoswatter
A: 

I think it was a design choice.

The first syntax looks good. I would want to have it too. However, the second one is more structured. You don't create nested namespaces this way:

Hello::World::Everyone::Great {

}

Will you declare this beforehand?

Xolve
@Xolve: Yes, I would rather have more classification of software components. Languages like Java and C# both allow this kind of syntax, and it works just fine for them. They both also ship with extremely large standard libraries, and the hierarchy used to classify things into namespaces makes it much easier to find the component you are looking for.
Billy ONeal