Specifying C++ symbols in C++ namespaces

Daniel Kozák kozzi11 at gmail.com
Thu Apr 3 04:06:56 PDT 2014


V Thu, 3 Apr 2014 06:36:54 -0400
Michel Fortin <michel.fortin at michelf.ca> napsáno:

> On 2014-04-03 03:48:18 +0000, Walter Bright
> <newshound2 at digitalmars.com> said:
> 
> > On 4/2/2014 7:14 PM, Michel Fortin wrote:
> >> That's a contrived example.
> > 
> > Not at all. The whole point of using namespaces in C++ is to
> > introduce a scope. And the whole point of scopes is to have the
> > same name in different scopes represent different objects.
> > 
> >> Perhaps I'm wrong, but I'd assume the general use
> >> case is that all functions in a module will come from the same C++
> >> namespace.
> > 
> > I believe that is an incorrect assumption. C++ namespaces were 
> > specifically (and wrongly, in my not so humble opinion, but there
> > it is) not designed to be closed, nor have any particular
> > relationship with modules.
> > 
> >> Alternatively you can use another module for the other namespace.
> > 
> > Forcing C++ code that exists in a single file to be split up among 
> > multiple D files is inflicting unnecessary punishment on the poor
> > guy trying to justify migrating to D.
> 
> Ok, let's assume that we actually want to reproduce the C++ file 
> structure then. Let us have a C++ project, with two files. I'll 
> temporarily use the 'namespace' keyword on the D side until we can 
> decide on how to best represent a namespace:
> 
>       module foo;
>       extern (C++):
> 
>       namespace S { namespace T {
>          int foo();
>          namespace U {
>              int foo();
>          }
>       } }
> 
> 
>       module bar;
>       extern (C++):
> 
>       namespace S { namespace T {
>          int bar();
>          namespace U {
>              int bar();
>          }
>       } }
> 
> Now let's use those:
> 
>       module main;
>       import foo;
>       import bar;
> 
>       void main() {
>           S.T.foo();
>           S.T.U.bar();
>       }
> 
> But how does the lookup for those functions work? If we use structs
> or templates to represent those namespaces in D then you'll have to 
> specify the module name to disambiguate the struct/template itself,
> and the namespace just becomes a nuisance you have to repeat over and
> over:
> 
>       void main() {
>           .foo.S.T.foo();
>           .bar.S.T.U.bar();
>       }
> 
> Here I'd argue that having whole-module namespaces in D makes no
> sense. So let's retry by peeling the "S.T" part of the namespace:
> 
>       module foo;
>       extern (C++, S.T):
> 
>       int foo();
>       namespace U {
>           int foo();
>       }
> 
> 
>       module bar;
>       extern (C++, S.T):
> 
>       int bar();
>       namespace U {
>           int bar();
>       }
> 
> 
>       module main;
>       import foo;
>       import bar;
> 
>       void main() {
>           foo();
>           .bar.U.bar();
>       }
> 
> Better. Still, if you want C++ namespaces to work nicely, you'll have 
> to introduce first class namespace support in D. That means that 
> identical namespaces are "merged" into each other when you import 
> modules that contain them. It'd allow you to write this:
> 
>       void main() {
>           foo();
>           U.bar();
>       }
> 
> Still, I'm not convinced that'd be terribly helpful. Namespaces in D 
> would make it easier to declare things 1:1 for sure, but anything
> that depends on Koenig lookup[1] will be broken in D. It could even
> be silently broken as no Koenig lookup means another function not in
> a namespace could be used silently instead of the expected one in a 
> namespace (assuming a naive port of some C++ code).
> 
> [1]: https://en.wikipedia.org/wiki/Argument-dependent_name_lookup
> 
> I'd tend to simply implement extern(C++, namespace.here), which
> should work fine to wrap single-namespace cpp files, and wait to see
> what are the actual friction points before introducing more (people
> can experiment with structs or other modules meanwhile).
> 
> 

I think we should distinguish modules lookup from namespaces lookup.
Something like this:

A.B.foo() // call foo function from module/struct/class A and B
#A.#B.foo // call foo function from namespaces A and B
or
A::B.foo // call foo function from namespaces A and B
or
/A/B.foo // call foo function from namespaces A and B



More information about the Digitalmars-d mailing list