On Wednesday, 6 January 2016 at 05:14:30 UTC, Carl Sturtivant wrote:

OK, I'm going to state the obvious here in the hope it will be considered afresh. :)

On Sunday, 3 January 2016 at 17:53:38 UTC, Walter Bright wrote:
5. I don't share the opinion that a C++ namespace introducing a scope, just as it does in C++, is something weird and unexpected.

Wait a second: D has modules with clever import rules and no global scope to manage name collisions instead of namespaces. See the bullet here under "features to drop from C++":
http://dlang.org/overview.html#features_to_drop

What's now going on is the reintroduction of this dropped feature in a way that is at cross purposes to the underlying D language philosophy.

In the end the disputed difficult comes down to this:
    extern(C++, ns1) int fn(int x);
and
    extern(C++, ns2) int fn(int x);
have different mangled names but the same D-source name. They also have the same C++ source name.

In the C++ source this collision is averted by namespaces. In the D source where the namespace mechanism has been designed out in favor of the module mechanism, this collision should be averted using the module mechanism.

If you still believe you want to be able to place the colliding externals in the same module, i.e. not use D's collision avoidance mechanism, what's needed is simply the ability to have two different D source names for the two functions specified in the two declarations. This is just a name change, not an entire new scope with all the complexity that would entail in the namespace situation.

Perhaps there's a way to do this in D already: how do you link to a C function whose name is 'new' or some other D keyword?

In any case, drawing a distinction between the D source name and the C++ source name (or the external source name in general) in the external declaration would do the job. e.g.

extern(C++, ns1, fn) int fn1(int x);
extern(C++, ns2, fn) int fn2(int x);

In each case the external declaration has enough information to compute the mangled name and attach it to a D source name without collision.

My opinion: Injecting C++ bad design into D in the name of linkage is wrong, ugly, and over complicated. I don't think the alternative mechanism suggested in the preceding paragraph or anything similar is necessary either, since D modules are the replacement for namespaces in going from C++ to D, and they can do the job. But something like that alternative is a lot less awful.

A clean design for external C++ linkage that handles namespaces could simply involve extending #pragma(mangle,.......) to take a quoted namespace. This keeps extern() simple as a purely linkage/mangling related qualification, as expected, with no extra scope simulating a namespace being introduced.

A name collision in the existing machinery,
    extern(C++,ns1) int fn(int x);
    extern(C++,ns2) int fn(int x);
could instead be a compiler error, and be averted by e.g. the following new mechanism.

#pragma(mangle, "fn", "ns1")
extern(C++) int fn1(int x);

#pragma(mangle, "fn", "ns2")
extern(C++) int fn2(int x);

Maybe the C++ namespace's name could be permitted either quoted in the pragma as above (so that names that are D keywords can be accommodated) or implicitly taken up by the pragma from the external declaration as in the following.

#pragma(mangle, "fn")
extern(C++, ns1) int fn1(int x);

#pragma(mangle, "fn")
extern(C++, ns2) int fn2(int x);

Of course most of the time this wouldn't be used, because the offending declarations can be placed in different D modules. So then linkage to C++ is handled like linkage to C, simply!


Reply via email to