Topic: Nested namespace syntactic sugar


Author: "Greg Herlihy" <greghe@pacbell.net>
Date: Sun, 25 Jun 2006 20:19:03 CST
Raw View
Manfred von Willich wrote:
> I would propose this syntactic sugar be introduced in the standard,
> such the following two constructs be treated as identical in all
> contexts (extended to any level of nesting):
>
> namespace spaceX::spaceY { ...other stuff... }
>
> and
>
> namespace spaceX { namespace spaceY { ...other stuff... } }
>
> >From searching the various issues lists
> (http://www.open-std.org/JTC1/SC22/WG21), I am aware that there is a
> related issue (closed issues list rev 41, issue 311), however I think
> in this, I concur with Jonathan Caves.  There may be ongoing work in
> this area, of which please let me know (I'm not sure how to access such
> work).  In raising this this form, I hope I will not be reviving old
> arguments.
>
> My argument is as follows:
>    - The construct cannot occur in code conforming to the existing
> standard, and it thus cannot break existing code.
>    - No new keyword are needed.
>    - Non-compliant compilers that do accept it almost certainly use a
> compatible interpretation
>    - There is valuable utility in the change: It is a pain to have code
> in which the "correct" indentation is large, and changes when the
> namespace hierarchy is changed.
>    - Other languages successfully use the equivalent (e.g. C#, Java's
> "package")
>
> Treating this a pure syntactic sugar (i.e. the interpretation maps
> directly to an existing construct), I do not see room for
> misinterpretation.  Thus, it should be allowed when declaring
> namespaces and when reopening them.

The double colon operator (::) in C++ usually separates names that have
already been defined. That is, by the time X::A appears in a source
file, X has either been declared a class or namespace and A has already
been declared within it. Granted, there is at least one exception: a
friend declaration can introduce a new name through a colon declaration
- although this result is often not what the programmer intended.

Nevertheless having a double colon appear in a declaration (instead of
in a definition for a previous declaration) would be another (and more
significant) exception to this convention - and would of course further
complicate the task of parsing C++ code. The fact that the construct is
"syntactic sugar" does not necesarily make it easier to parse - but
certainly makes an argument against adopting it - since it adds nothing
that is not already supported in the language.

All other issues aside, I would question the alleged benefit itself:
that is, whether streamlining nested namespace declarations is a
desirable goal. I argue that it is not. I think that declaring deeply
nested namespaces in C++ should be something of a chore - because
writing client code that uses deeply nested names is not in the least
convenient. In other words, there is cost in creating nested namespaces
that should not minimized for anyone inclined to make such
declarations. So if some implementor is determined to declare a set of
nested namespaces five levels deep - I would rather have them have to
open each namespace explicitly and do so five times - because there is
a greater chance that at some point in this process they may ask
themselves: "hmmm...do I really this many levels of namespaces?"
Whereas if the task can be accomplished with a one-line declaration -
then the chance that that question would ever be raised is remote. And
in that case it would be clients of this interface who would be the
ones to bear the cost of this convenience.

Greg

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: news@derived-software.ltd.uk ("Phil Richards")
Date: Mon, 26 Jun 2006 14:29:32 GMT
Raw View
On Sun, 25 Jun 2006 20:19:03 -0600, Greg Herlihy wrote:
> Manfred von Willich wrote:
>> I would propose this syntactic sugar be introduced in the standard,
>> such the following two constructs be treated as identical in all
>> contexts (extended to any level of nesting): namespace spaceX::spaceY {
>> ...other stuff... }
[...]
> The double colon operator (: in C++ usually separates names that have
> already been defined. [...]
> Nevertheless having a double colon appear in a declaration (instead of
> in a definition for a previous declaration) would be another (and more
> significant) exception to this convention - and would of course further
> complicate the task of parsing C++ code. The fact that the construct is
> "syntactic sugar" does not necesarily make it easier to parse - but
> certainly makes an argument against adopting it - since it adds nothing
> that is not already supported in the language.

So, there are already exceptions that mean that the parser is already
complicated to some extent.  However, in this particular case, I don't see
that it *does* complicate the grammar particularly.  Why? Because there is
already a construct in the grammar that matches to the new rule: the one
that allows the RHS of a namespace alias to be parsed.

> All other issues aside, I would question the alleged benefit itself:
> that is, whether streamlining nested namespace declarations is a
> desirable goal. I argue that it is not. I think that declaring deeply
> nested namespaces in C++ should be something of a chore - because
> writing client code that uses deeply nested names is not in the least
> convenient.

Surely that is a decision to be made by the implementer and their client?
I'd hate to think were C++ would be if it took on the duty of policing
some particular design philosophy :(  If I want to have 5 levels of
namespaces, and the language supports it, then why make it *so* hard? If
the client wants short names, they can use namespace aliases, after all.

Basically, this change would have made my life a lot easier - and it would
even if I'm only dealing with namespace hierarchies two or three levels
deep.  It's also one that I've often wondered "why isn't this allowed?"

Phil

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Andrei Polushin" <polushin@gmail.com>
Date: Mon, 26 Jun 2006 09:28:00 CST
Raw View
Greg Herlihy wrote:
> All other issues aside, I would question the alleged benefit itself:
> that is, whether streamlining nested namespace declarations is a
> desirable goal. I argue that it is not. I think that declaring deeply
> nested namespaces in C++ should be something of a chore - because
> writing client code that uses deeply nested names is not in the least
> convenient. In other words, there is cost in creating nested namespaces
> that should not minimized for anyone inclined to make such
> declarations. So if some implementor is determined to declare a set of
> nested namespaces five levels deep - I would rather have them have to
> open each namespace explicitly and do so five times - because there is
> a greater chance that at some point in this process they may ask
> themselves: "hmmm...do I really this many levels of namespaces?"
> Whereas if the task can be accomplished with a one-line declaration -
> then the chance that that question would ever be raised is remote. And
> in that case it would be clients of this interface who would be the
> ones to bear the cost of this convenience.

The actual problem is uniqueness. Uniqueness is an important benefit
for the concurrent/distributed development, because anybody can be sure
that his declarations will never conflict with others' work.

If you want your namespace to have unique name, you should follow some
hierarchical convention, like

   namespace net {
      namespace pacbell {
         namespace cool {
            class A {
            };
         }
      }
   }

   using net::pacbell::cool::A;

With this convention, the namespace net::pacbell is reserved for the
owner of http://pacbell.net domain and the declarations in this
namespace are both mnemonic and world-unique.

There should be some solution for uniqueness problem: it must be
convenient to declare unique namespaces, and

1. Simplifying declaration of hierarchical namespace is the most
   obvious way to go.

Other possible solutions are

2. Use undersore-separated namespace names:

   namespace net_pacbell_cool {
      class A {
      };
   }

   using net_pacbell_cool::A;

3. Use some ugly macros:

   #define NET_PACBELL_COOL_BEGIN namespace net { ... { ... {
   #define NET_PACBELL_COOL_END   }}}
   #define NET_PACBELL_COOL_NS    ::net::pacbell::cool

   NET_PACBELL_COOL_BEGIN
      class A {
      };
   NET_PACBELL_COOL_END

   using NET_PACBELL_COOL_NS::A;

4. Allow unique string instead of namespace name:

   namespace "http://pacbell.net/cool/" {
      class A {
      };
   }
   using "http://pacbell.net/cool/"::A;


Which one do you prefer?


--
Andrei Polushin

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: musiphil@bawi.org (Seungbeom Kim)
Date: Mon, 26 Jun 2006 23:11:29 GMT
Raw View
Andrei Polushin wrote:
>
> The actual problem is uniqueness. [...]
>
> If you want your namespace to have unique name, you should follow some
> hierarchical convention, like
>
>    namespace net {
>       namespace pacbell {
>          namespace cool {
>             class A {
>             };
>          }
>       }
>    }
>
>    using net::pacbell::cool::A;
>
> With this convention, the namespace net::pacbell is reserved for the
> owner of http://pacbell.net domain and the declarations in this
> namespace are both mnemonic and world-unique.
>
> There should be some solution for uniqueness problem: it must be
> convenient to declare unique namespaces, and
>
> 1. Simplifying declaration of hierarchical namespace is the most
>    obvious way to go.
>
> Other possible solutions are
>
> 2. Use undersore-separated namespace names:
>
>    namespace net_pacbell_cool {
>       class A {
>       };
>    }
>
>    using net_pacbell_cool::A;

I don't see any problem with this, which is available today and
with which you don't even have to reverse the order of the components.

Mapping from a domain name to a namespace name is a convention anyway,
and not something a language standard can/should specify; mapping from
"pacbell.net" to "pacbell_net" seems as good to me as to "net::pacbell".

> 3. Use some ugly macros:
>
>    #define NET_PACBELL_COOL_BEGIN namespace net { ... { ... {
>    #define NET_PACBELL_COOL_END   }}}
>    #define NET_PACBELL_COOL_NS    ::net::pacbell::cool
>
>    NET_PACBELL_COOL_BEGIN
>       class A {
>       };
>    NET_PACBELL_COOL_END
>
>    using NET_PACBELL_COOL_NS::A;

This is a variant of method 1, but I don't see any gain with
using macros like this.

> 4. Allow unique string instead of namespace name:
>
>    namespace "http://pacbell.net/cool/" {
>       class A {
>       };
>    }
>    using "http://pacbell.net/cool/"::A;

This looks cool, but allowing arbitrary string literals for symbol names
doesn't seem very feasible in terms of linking, and I think the original
problem can be solved without adopting a new feature like this anyway.

--
Seungbeom Kim

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Manfred von Willich" <manfred@techniroot.co.za>
Date: Wed, 28 Jun 2006 16:56:40 CST
Raw View
Greg Herlihy wrote:
>
> The double colon operator (::) in C++ usually separates names that have
> already been defined. <snip> - and would of course further
> complicate the task of parsing C++ code. The fact that the construct is
> "syntactic sugar" does not necesarily make it easier to parse - but
> certainly makes an argument against adopting it - since it adds nothing
> that is not already supported in the language.

I don't think there is any strong rationale to stick with this
convention (i.e. not introducing a name in association with ::).
Anyhow, syntactic sugar is by definition something non-standard without
adding new support, to make the program simpler and/or more intuitive.
The parsing complexity argument, followed consistently, would have us
believe that we should be using a non-macro assembler, not a C++
compiler.


"Phil Richards" wrote:
> > All other issues aside, I would question the alleged benefit itself:
> > that is, whether streamlining nested namespace declarations is a
> > desirable goal. I argue that it is not. I think that declaring deeply
> > nested namespaces in C++ should be something of a chore - because
> > writing client code that uses deeply nested names is not in the least
> > convenient.
>
> Surely that is a decision to be made by the implementer and their client?
> I'd hate to think were C++ would be if it took on the duty of policing
> some particular design philosophy :(  If I want to have 5 levels of
> namespaces, and the language supports it, then why make it *so* hard? If
> the client wants short names, they can use namespace aliases, after all.
>
> Basically, this change would have made my life a lot easier - and it would
> even if I'm only dealing with namespace hierarchies two or three levels
> deep.  It's also one that I've often wondered "why isn't this allowed?"
>
> Phil

I'm definitely with Phil on this one. Deeply nested namespaces can be
and are used very effectively.  I think the number of times variations
of this theme have been raised in various guises (including by Bjarne
Stroustrup) indicates that the utility would be significant.

I would suggest that Greg is off-beam saying "writing client code that
uses deeply nested names is not in the least convenient" - surely the
"using namespace" directive provides convenience and control at the
same time for the client, regardless of depth of nesting?


Seungbeom Kim wrote:
> Andrei Polushin wrote:
> >
> > The actual problem is uniqueness. [...]

Uniqueness not the only problem solved by namespaces.  Namespaces also
neatly control visibility of other namespaces.

> >
> > There should be some solution for uniqueness problem: it must be
> > convenient to declare unique namespaces, and
> >
> > 1. Simplifying declaration of hierarchical namespace is the most
> >    obvious way to go.

I think many of us are with Andrei on #1.

> >
> > Other possible solutions are
> >
> > 2. Use undersore-separated namespace names:
> >
> >    namespace net_pacbell_cool {
> >       class A {
> >       };
> >    }
> >
> >    using net_pacbell_cool::A;
>
> I don't see any problem with this, which is available today and
> with which you don't even have to reverse the order of the components.

There is a problem with this - the namespace hierarchy becomes merely a
convention, since the nesting visibility must be provided explicitly by
the programmer (which can work after a fashion), e.g.:

   namespace net {
   }
   namespace net_pacbell {
      using namespace net;
   }
   namespace net_pacbell_cool {
      using namespace net;
      using namespace net_pacbell;
   }

> > 3. Use some ugly macros...

That's unfortunately what they are: ugly.  There seems to be a move
away from reliance on the preprocessor to provide what is lacking in
the language, and to move towards providing what is needed directly in
the language, and I fully endorse this.

A "neater" version of this (#3) is to collapse the intro and closing
onto one line each (no macros):

   namespace net { namespace pacbell { namespace cool {
      ...
   }}}

> > 4. Allow unique string instead of namespace name: <snip>

Ouch.  I'd rather use the essentially equivalent non-string variant #2
(assuming there are no visibility rules for partially matching
strings).


To add another variant (to those suggested by Andrei, not to be
confused with his variant #2) that I have resorted to (using VC6):

   // File proj.h:
   // declaration of nesting structure (typ. in a project-level
include-file)
   namespace net {
      namespace pacbell {
         namespace cool {
            class A;
            class B;
         }
         class C;
      }
   }
   namespace net_pacbell = net::pacbell;
   namespace net_pacbell_cool = net::pacbell::cool;

   // File net/pacbell/cool.h:
   #include "proj.h"
   namespace one_two_three { // reopened, no nesting
      // Beware of VC6 "using namespace" bugs
      class A {
         ...
      };
      class B {
         ...
      };
   }

I think my syntatctic sugar suggestion has merit, but I think the
committee may be unsympathetic because they have seen it in forms that
had unknown risks attached.  The only counterargument to the suggestion
I've seen that I consider vaguely sound is parsing complexity, and as I
said above, that is an argument against using compilers at all.

Manfred

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Greg Herlihy" <greghe@pacbell.net>
Date: Wed, 28 Jun 2006 23:02:37 CST
Raw View
"Phil Richards" wrote:
> On Sun, 25 Jun 2006 20:19:03 -0600, Greg Herlihy wrote:
..
> > All other issues aside, I would question the alleged benefit itself:
> > that is, whether streamlining nested namespace declarations is a
> > desirable goal. I argue that it is not. I think that declaring deeply
> > nested namespaces in C++ should be something of a chore - because
> > writing client code that uses deeply nested names is not in the least
> > convenient.
>
> Surely that is a decision to be made by the implementer and their client?
> I'd hate to think were C++ would be if it took on the duty of policing
> some particular design philosophy :(  If I want to have 5 levels of
> namespaces, and the language supports it, then why make it *so* hard? If
> the client wants short names, they can use namespace aliases, after all.
>
> Basically, this change would have made my life a lot easier - and it would
> even if I'm only dealing with namespace hierarchies two or three levels
> deep.  It's also one that I've often wondered "why isn't this allowed?"

A better question would be "what use is this feature?" Unless the goal
is to create namespaces en masse that contain only other namespaces
(which wouldn't make a lot of sense), then why would it ever be
necessary to open a namespace more than the next level deep?
Presumably, the named, intervening namespaces in the proposed syntax
will still be opened explicitly elsewhere (in order for content to be
added to them), so where is the savings? After all, why not declare the
inner namespaces of a particular namespace while that namespace is
open?

In other words, the feature doesn't deliver any benefit to a set of
nested namespaces that could not be attained simply through better
organization. And by like measure, this syntax would encourage
disorganized namespace by making it easier to sprinkle the contents of
an inner namespace throughout its enclosing namespace (whose contents
in turn could then be more easily strewn throughout its parent
namespace, and so forth).

Greg

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: news@derived-software.ltd.uk ("Phil Richards")
Date: Thu, 29 Jun 2006 21:58:50 GMT
Raw View
On Wed, 28 Jun 2006 23:02:37 -0600, Greg Herlihy wrote:
[in reply to me asking why namespace A::B::C { ... } isn't allowed?"]
> A better question would be "what use is this feature?" Unless the goal
> is to create namespaces en masse that contain only other namespaces
> (which wouldn't make a lot of sense), then why would it ever be
> necessary to open a namespace more than the next level deep?

Ever written a header file that looks like:
 namespace A {
 namespace B {
 namespace C {
 struct D ...
 }}}

?  I know I have.  And I know that Boost have.

I'd like to be able to write:
 namespace A::B::C {
 struct D ...
 }

Now, I know which one *I* find more readable.  And they would be
semantically identical.  It also makes it vastly simpler to have:
 #define MY_NAMESPACE ...whatever I feel like...

 namespace MY_NAMESPACE {
 }

without having to do incredibly ugly things like:

 #define OPEN_MY_NAMESPACE namespace ... { namespace ...
 #define CLOSE_MY_NAMESPACE }}...

OPEN_MY_NAMESPACE
.
CLOSE_MY_NAMESPACE

Now, whether it should be possible to have:
 namespace ::A::B {
 }
is a different (possibly harder) question.  And, if so, would:
 namespace :: {
 }
be allowed?

> Presumably, the named, intervening namespaces in the proposed syntax
> will still be opened explicitly elsewhere (in order for content to be
> added to them), so where is the savings?

No.  Why would you need to?

> After all, why not declare the
> inner namespaces of a particular namespace while that namespace is open?

Because I don't want to put my whole implementation in a single file,
which is the only way I can see that I can achieve what you have just
suggested...

Phil

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Manfred von Willich" <manfred@techniroot.co.za>
Date: Wed, 21 Jun 2006 10:22:22 CST
Raw View
I would propose this syntactic sugar be introduced in the standard,
such the following two constructs be treated as identical in all
contexts (extended to any level of nesting):

namespace spaceX::spaceY { ...other stuff... }

and

namespace spaceX { namespace spaceY { ...other stuff... } }

>From searching the various issues lists
(http://www.open-std.org/JTC1/SC22/WG21), I am aware that there is a
related issue (closed issues list rev 41, issue 311), however I think
in this, I concur with Jonathan Caves.  There may be ongoing work in
this area, of which please let me know (I'm not sure how to access such
work).  In raising this this form, I hope I will not be reviving old
arguments.

My argument is as follows:
   - The construct cannot occur in code conforming to the existing
standard, and it thus cannot break existing code.
   - No new keyword are needed.
   - Non-compliant compilers that do accept it almost certainly use a
compatible interpretation
   - There is valuable utility in the change: It is a pain to have code
in which the "correct" indentation is large, and changes when the
namespace hierarchy is changed.
   - Other languages successfully use the equivalent (e.g. C#, Java's
"package")

Treating this a pure syntactic sugar (i.e. the interpretation maps
directly to an existing construct), I do not see room for
misinterpretation.  Thus, it should be allowed when declaring
namespaces and when reopening them.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]