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!