Is there any good reason why C++ namespaces are "closed" in D?

Atila Neves atila.neves at gmail.com
Mon Aug 6 15:49:00 UTC 2018


On Friday, 3 August 2018 at 21:49:53 UTC, Walter Bright wrote:
> On 8/3/2018 3:58 AM, Atila Neves wrote:
>> I would only be able to alias a nested namespace once, since 
>> the code below obviously won't work:
>> 
>>     mixin CppNamespace0!() x;
>>     alias chrono = x.std.chrono;
>>     mixin CppNamespace1!() y;
>>     alias chrono = y.std.chrono;
>
> Try this:
>
>
>      mixin template X() {         // boilerplate prefix
>
>          extern (C++, std) extern(C++, chrono) int foo();   // 
> original line
>
>      } mixin X!() x; alias foo = x.std.chrono.foo;  // 
> boilerplate suffix

That doesn't solve the problem at all. I was toying with being 
able to have a nested namespace be an alias in a module. I can't 
realias chrono after the first `alias chrono = `, nor can I alias 
it to the different `chrono`s in all the different template 
mixins.


>> I considered for a while whether or not this would be truly 
>> bad, and the more I think about it the more convinced I am 
>> that Manu is right and there should be _no_ scoping whatsoever 
>> in D regarding C++ namespaces. We have packages and modules, 
>> we can use those to put the C++ functions we declare in 
>> whatever hierarchy we want.
>
> I am puzzled. With:
>
>   namespace std {
>      namespace chrono {
>          void foo();
>      }
>   }
>
>   namespace std {
>     namespace chrono {
>          void bar();
>     }
>   }
>
> you have stated that it is impractical for your translator to 
> rewrite this as:
>
>    namespace std {
>      namespace chrono {
>          void foo();
>          void bar();
>      }
>   }
>
> Ok, I get that. But it is practical to rewrite it as:
>
>    module std.chrono;
>    void foo();
>    void bar();
>
> ?

I don't understand what your question has to do with what you 
quoted. What I'm trying to say is that I think `extern(C++, 
foo.bar)` should NOT introduce a scope in D in any way, shape, or 
form. The D module/import/overload system should have no idea of 
what `foo` or `foo.bar` are - they don't exist.

>
> > I mean `std` should never be part of the fully qualified name
> of, for
> > instance, `core.stdcpp.exception.std.bad_exception`. It
> should just
> > be `core.stdcpp.exception.bad_exception` instead.
>
> C++ recognizes that, too, which is why it has "using" 
> declarations. D has the equivalent thing, "alias".
>
> You can do things like:
>
>     import std = core.stdcpp.exception;
>
> and then refer to:
>
>     std.bad_exception
>
> or:
>
>     import exception = core.stdcpp.exception;
>
>     exception.bad_exception;
>
> or whatever works best for one's project. Aliasing and import 
> renaming (which are really just more aliasing) is very capable, 
> and was designed for just these sorts of issues.

I think we're talking past each other. I know how to alias in D, 
and how to use `using` in C++. What I'm saying is that, with the 
file we have now (core.stdcpp.exception):

extern(C++, std) {
    class exception { /* ... */ }
}

Currently the fully qualified name of `exception` is 
`core.stdcpp.exception.std.exception`. I'm arguing that this is a 
mistake, and the the FQN should instead be 
`core.stdcpp.exception.exception`.

Yes, namespaces introduce scope in C++. Yes, lookup rules in C++ 
are crazy. The main points I'm (and, I think, Manu) arguing are:

1. We already have D packages, modules, and overload rules. We 
don't need to import any from C++
2. That namespaces introduce a scope in C++ does not mean that 
`extern(C++, ns)` should introduce one in D

i.e. Keep everything about D as-is, _except_ for no scoping for 
`extern(C++, ns)`.




More information about the Digitalmars-d mailing list