28

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.

TylerH
  • 20,799
  • 66
  • 75
  • 101
Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
  • My one thought on this is this sort of resembles declarations of things inside a class. I wonder if there would be some odd corners of specifying a class namespace vs. a namespace namespace that would be broken by your proposed syntax. – Omnifarious Aug 30 '10 at 19:22
  • "if you are unfortunate enough to be using a "dumb" bracket counting indentation tool." I know it's not the thrust of your argument, but you really can't ask the language to include features to support bad IDEs / code formatters / whatever. Under-featured tools, maybe, because the language wants to support a minimal development environment. Hence trigraphs. But not over-featured ones that go out of their way to damage your code. – Steve Jessop Aug 30 '10 at 20:43
  • 1
    @Steve: Actually, the fact that I think it's easier to read is the main reason I would like to see such a feature. – Billy ONeal Aug 30 '10 at 20:48
  • 1
    If you really want the rationale, you should ask this question on comp.std.c++, where people who actually write the Standard hang out :) – Pavel Minaev Aug 31 '10 at 16:18
  • 1
    This is included in C++17! http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4230.html – ante Jun 29 '16 at 12:27

5 Answers5

24

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
  • 348,265
  • 75
  • 913
  • 977
  • 1
    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 Aug 30 '10 at 19:38
  • Accepting the answer with the highest number of upvotes because I obviously cannot divine the true answer here. – Billy ONeal Aug 30 '10 at 21:46
  • For reference, this feature was indeed accepted for C++17. See the answer below by @Farway. – Rakete1111 Dec 18 '17 at 16:17
18

Nested namespace definition is part of the C++17 working draft.
This topic is mentioned in the proposal as an example of this feature being a programmers' demand original n4026 updated version: n4230.

Current latest draft: n4567 (paragraph 7.3.1 item 10)

7.3.1 Namespace Definition
...
10 A nested-namespace-definition with an enclosing-namespace-specifier E, identifier I and namespace-body B is equivalent to namespace E { namespace I { B } }

Example:

namespace A::B::C {
  int i;
}    The above has the same effect as:

namespace A {
  namespace B {
    namespace C {
      int i;
    }
  }
}

Compiler Support

GCC since version 6 enable using -std=c++1z
Visual C++ since 2015 update 3 enable using /std:c++latest
Clang since version 3.6 enable using -std=c++1z

Farway
  • 741
  • 10
  • 13
13

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
  • 99,783
  • 25
  • 219
  • 289
  • 6
    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 Aug 30 '10 at 19:37
  • 1
    @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 Aug 30 '10 at 19:41
  • 2
    @Omnifarious: I suppose you could use `namespace Hello::::World { }`, but I doubt anyone would support that :-P – James McNellis Aug 30 '10 at 19:43
  • @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. – AnT stands with Russia Aug 30 '10 at 19:43
  • @AndreyT: I meant having a namespace inside of an anonymous namespace. – Billy ONeal Aug 30 '10 at 19:51
  • @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 Aug 30 '10 at 20:37
  • @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 Aug 30 '10 at 20:54
  • @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 Aug 30 '10 at 21:00
  • +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 Aug 30 '10 at 21:02
  • @Potato: Do you have a code snippet for that? I can't figure out how to reproduce that. – James McNellis Aug 30 '10 at 21:05
  • @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 Aug 30 '10 at 21:10
  • @Potato: That error is expected though: the class named `X` in namespace `Y` hides the namespace named `X` introduced by the `using namespace ;` 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 Aug 30 '10 at 21:14
  • @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 Aug 30 '10 at 21:25
  • @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 Aug 30 '10 at 21:47
  • @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 Aug 30 '10 at 22:09
  • @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 Sep 09 '10 at 23:15
  • @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 Sep 09 '10 at 23:49
2

In C++ qualified names are reserved for referring to previously declared entities. This applies to both "sources" of qualified names: classes and namespaces.

TylerH
  • 20,799
  • 66
  • 75
  • 101
AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
0

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?

James McNellis
  • 348,265
  • 75
  • 913
  • 977
Xolve
  • 22,298
  • 21
  • 77
  • 125
  • 1
    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 Aug 30 '10 at 20:00