extern(C++, NS)

Manu via Digitalmars-d digitalmars-d at puremagic.com
Sun Nov 29 02:58:39 PST 2015


On 29 November 2015 at 20:17, Iain Buclaw via Digitalmars-d
<digitalmars-d at puremagic.com> wrote:
> On 29 Nov 2015 6:17 am, "Manu via Digitalmars-d"
> <digitalmars-d at puremagic.com> wrote:
>>
>> On 29 November 2015 at 14:57, Walter Bright via Digitalmars-d
>> <digitalmars-d at puremagic.com> wrote:
>> >
>> > D does not support C++ semantics. You cannot split namespaces into
>> > multiple
>> > files in D, nor can you add symbols to an existing namespace. For
>> > namespace
>> > NS, all the declarations in NS have to be in one file and between the {
>> > },
>> > just like any other scope in D.
>>
>> Then the feature fails. You can't put the entire STL in one file.
>> C++ doesn't namespace per file, it generally namespaces per project...
>> so this is the common case; every module define symbols in the same
>> C++ namespace.
>>
>>
>
> This (and response below about mangling) answers a recent question in a PR I
> made.  I had noticed the same when writing a testsuite case, only to
> discover you can only declare `extern(C++, std)` once.  For me, having all
> related code for a test close together is a nice-to-have though.

It's a serious problem. I haven't been able to find any reasonable
solution. I've tried a bunch of stuff.
I think the cleanest solutions would be to either fix this, or to
allow public aliasing of private namespaces, that way the namespace is
kept in it's box and never pollutes the user's module scope on import.


>> >> Additionally to that, I don't really want the C++ namespaces to be
>> >> visible to D; they should be for mangling purposes only.
>> >
>> >
>> > We considered making them for mangling only, and rejected it as
>> > unworkable,
>> > because then two identical names in different namespaces could not be
>> > distinguished by the D symbol table system.
>>
>> I understand, and that's fine, but it's not particularly useful unless
>> I can make the namespace invisible and alias the namespaced symbols
>> into D's module (user-accessible) scope. Otherwise importing 2 modules
>> leads to conflicting namespace and symbol resolution is all messed up.
>>
>
> Renamed imports should work here?

How? I tried this every way I could think;

import x.y.NS : Thing; // expects that NS is a file...
import x.y : Thing = NS.Thing; // doesn't like 'NS.' in this statement
import x.y : this = NS; // ...or something. yeah, I was getting hopeful

I could only make this work with a proxy module, which doubles my module count:

internal/thing.d:
  module x.y.internal.thing;
  extern(C++, NS) struct Thing {}

thing.d:
  module x.y.thing;
  import x.y.internal.thing; // pollutes the local namespace with NS,
but since it's not public it doesn't cascade outwards
  alias Thing = NS.Thing; // aliases to a public module-level symbol

user.d:
  import x.y.thing;
  Thing t; // hooray, it works!


>> >> So I try code like this:
>> >>    private extern(C++, NS) struct Thing {}
>> >>    alias Thing = NS.Thing;
>> >>
>> >> The idea being that NS will not be available externally, and they
>> >> should use Thing in module scope instead, but that doesnt work with
>> >> errors:
>> >>    Error: module blah class blah.NS.Thing is private
>> >>
>> >> It seems aliasing a private thing into the public namespace does not
>> >> make it accessible via that alias?
>> >
>> >
>> > Aliases do not change access permissions. They are just aliases.
>>
>> Maybe a special case for C++ namespaces? Or some other solution that
>> produces the same result.
>> It's a weird sort of permission this one, it's not that the symbols
>> are 'private'; I intend the user to use them, I just want the C++
>> hierarchy excluded from the symbol table and only accessibly by
>> controlled/explicit alias.
>>
>
> You may have already noticed, but `extern(C++, NS)` behaves more like
> importing a module, but rather than the module being in a separate file,
> it's contents are put inplace of the braces.

Yup, but `import` doesn't seem to have tools to deal with this case.

> Like importing modules in D, the namespace name itself is not a strong
> encapsulation (unlike e.g D enums), so whether you use Thing or NS.Thing,
> both will resolve to the same symbol.  The same should also be true when
> importing a namespace from another module.

It all goes south when you realise that every file in a C++ project
tends to be in the same namespace.
Import 2 of them, and then they start hiding eachother, and it all
goes south very quickly.

> I think your idea with aliases was just wishful thinking, aliases themselves
> never worked like that.

I thought aliases did produce a symbol in the scope they are declared?
Or do you mean with the private thing? Yeah...
Aliases are often used to sort out these sorts of scope/namespacing
issues, I've seen it come up lots of times.


More information about the Digitalmars-d mailing list