www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - extern(C++, ns)

reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
C++ namespacing is causing me endless, and I mean *endless* trouble.
This idea that we express the C++ namespace hierarchy in D is the main
problem.
I don't think C++ namespaces should interfere with D scoping rules, they
should be purely for mangling.
It creates a whole bundle of edge cases which either don't have work
arounds, or REALLY awkward workarounds which typically have a heavy impact
on all the regular D code that the C++ code interacts with.

Not least of which is that C++ namespaces usually span the entire project,
and in D a C++ namespace can only appear in one module ever.
Declaring symbols with the same C++ namespace in different modules leads to
multiple definition errors, and if you are super-careful to avoid those,
you gain name resolution issues in it's place.

It is also very awkward that a C++ namespace can't be the same as a top
level package name. My top level package is named the same as one of my C++
namespaces... what do I do? It gets ugly real fast.

The main problem extends from this situation:

module x.y;

extern(C++, ns) struct Y {}


module ns.m;

import x.y; // fail, the c++ namespace is already present (top level module)
import x.y : ns.Y; // fail, '.' can't appear here
import x.y : Y; // fail, not found

// This **sometimes** works, and it's very brittle
static import x.y;
alias Y = x.y.Y;


Thing is, I'm not declaring a C++ object, I'm declaring a D object, the
only thing being that struct's take care to maintain common binary layout,
and functions just mangle like C++ so that my code links. I'm in D, I'm
declaring my stuff in the D module where it should be scoped, and where
other D code should expect to find it. I don't see any point in building
the C++ hierarchy in this space. C++ namespace rules are incompatible with
D; you can litter them through C++ code, and add new symbols to C++
namespaces from anywhere... this is fundamentally incompatible with D, and
no further reasoning should be required to conclude that it can't be
reproduced, so it should be for mangling purposes only.

I have spent **days**, actually, weeks of my free time trying to make my
tiny bit of code build, and it's just nothing but trouble after trouble. I
have completely restructured my code at least 3 times to try and find a way
to make it fit together in a way that's both practical and works, but I
just can't. It always hits some brick wall somewhere.

extern(C++, NS) looks okay in isolated tests/experiments, but try and
actually use it, and you will become very frustrated.

Please, fix this. I'm almost done. I'm really struggling to keep this dream
alive.
Jan 02
next sibling parent reply Rikki Cattermole <alphaglosined gmail.com> writes:
On 03/01/16 5:54 PM, Manu via Digitalmars-d wrote:
 C++ namespacing is causing me endless, and I mean *endless* trouble.
 This idea that we express the C++ namespace hierarchy in D is the main
 problem.
 I don't think C++ namespaces should interfere with D scoping rules, they
 should be purely for mangling.
 It creates a whole bundle of edge cases which either don't have work
 arounds, or REALLY awkward workarounds which typically have a heavy
 impact on all the regular D code that the C++ code interacts with.

 Not least of which is that C++ namespaces usually span the entire
 project, and in D a C++ namespace can only appear in one module ever.
 Declaring symbols with the same C++ namespace in different modules leads
 to multiple definition errors, and if you are super-careful to avoid
 those, you gain name resolution issues in it's place.

 It is also very awkward that a C++ namespace can't be the same as a top
 level package name. My top level package is named the same as one of my
 C++ namespaces... what do I do? It gets ugly real fast.

 The main problem extends from this situation:

 module x.y;

 extern(C++, ns) struct Y {}


 module ns.m;

 import x.y; // fail, the c++ namespace is already present (top level module)
 import x.y : ns.Y; // fail, '.' can't appear here
 import x.y : Y; // fail, not found

 // This **sometimes** works, and it's very brittle
 static import x.y;
 alias Y = x.y.Y;


 Thing is, I'm not declaring a C++ object, I'm declaring a D object, the
 only thing being that struct's take care to maintain common binary
 layout, and functions just mangle like C++ so that my code links. I'm in
 D, I'm declaring my stuff in the D module where it should be scoped, and
 where other D code should expect to find it. I don't see any point in
 building the C++ hierarchy in this space. C++ namespace rules are
 incompatible with D; you can litter them through C++ code, and add new
 symbols to C++ namespaces from anywhere... this is fundamentally
 incompatible with D, and no further reasoning should be required to
 conclude that it can't be reproduced, so it should be for mangling
 purposes only.

 I have spent **days**, actually, weeks of my free time trying to make my
 tiny bit of code build, and it's just nothing but trouble after trouble.
 I have completely restructured my code at least 3 times to try and find
 a way to make it fit together in a way that's both practical and works,
 but I just can't. It always hits some brick wall somewhere.

 extern(C++, NS) looks okay in isolated tests/experiments, but try and
 actually use it, and you will become very frustrated.

 Please, fix this. I'm almost done. I'm really struggling to keep this
 dream alive.
Ok, so what I gathered from that is that if a D package/module matches a C++ one in scope, D will only be checked. The obvious answer would be to rename the D side, but that really isn't good enough. Since I'm in no position to help, well this is a bit useless comment.
Jan 02
parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 3 January 2016 at 15:17, Rikki Cattermole via Digitalmars-d <
digitalmars-d puremagic.com> wrote:
 Ok, so what I gathered from that is that if a D package/module matches a
 C++ one in scope, D will only be checked.
No, you name conflict error. But that's not the main problem I'm talking about, which is that namespace scopes are created and break everything.
 The obvious answer would be to rename the D side, but that really isn't
 good enough.
You don't just go and rename an entire existing project, which is a lib in this case (so, also rename all the clients...?) because you need to type extern(C++) somewhere :/
Jan 02
parent reply Rikki Cattermole <alphaglosined gmail.com> writes:
On 03/01/16 6:26 PM, Manu via Digitalmars-d wrote:
 On 3 January 2016 at 15:17, Rikki Cattermole via Digitalmars-d
 <digitalmars-d puremagic.com <mailto:digitalmars-d puremagic.com>> wrote:

     Ok, so what I gathered from that is that if a D package/module
     matches a C++ one in scope, D will only be checked.


 No, you name conflict error. But that's not the main problem I'm talking
 about, which is that namespace scopes are created and break everything.

     The obvious answer would be to rename the D side, but that really
     isn't good enough.


 You don't just go and rename an entire existing project, which is a lib
 in this case (so, also rename all the clients...?) because you need to
 type extern(C++) somewhere :/
Hang on I just tried this on Windows: module ns.m; import x.y; // import x.y : ns.Y; // doesn't work grr import x.y : Y; module x.y; extern(C++, ns) { struct Y { } } Does this work for you?
Jan 02
next sibling parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 3 January 2016 at 15:45, Manu <turkeyman gmail.com> wrote:

 On 3 January 2016 at 15:34, Rikki Cattermole via Digitalmars-d <
 digitalmars-d puremagic.com> wrote:

 On 03/01/16 6:26 PM, Manu via Digitalmars-d wrote:

 On 3 January 2016 at 15:17, Rikki Cattermole via Digitalmars-d
 <digitalmars-d puremagic.com <mailto:digitalmars-d puremagic.com>>
 wrote:

     Ok, so what I gathered from that is that if a D package/module
     matches a C++ one in scope, D will only be checked.


 No, you name conflict error. But that's not the main problem I'm talking
 about, which is that namespace scopes are created and break everything.

     The obvious answer would be to rename the D side, but that really
     isn't good enough.


 You don't just go and rename an entire existing project, which is a lib
 in this case (so, also rename all the clients...?) because you need to
 type extern(C++) somewhere :/
Hang on I just tried this on Windows: module ns.m; import x.y; // import x.y : ns.Y; // doesn't work grr import x.y : Y; module x.y; extern(C++, ns) { struct Y { } } Does this work for you?
The short answer is, "most of the time". I've been using recursive modules to place extern(C++) declarations in a sensible scope quite a lot. It breaks sometimes, not sure why... suspect it's related to forward referencing, or multiple/semi-circular imports.
For instance, connecting to the C++ string lib: module libep.string; public import libep.c.string : BaseString, MutableString, SharedString; alias String = BaseString!char; alias WString = BaseString!wchar; alias DString = BaseString!dchar; Those don't like to be imported that way: Error: template instance BaseString!char BaseString is not a template declaration, it is a alias If I instead: module libep.string; static import libep.c.string; alias BaseString = libep.c.string.BaseString; alias MutableString = libep.c.string.MutableString; alias SharedString = libep.c.string.SharedString; alias String = BaseString!char; alias WString = BaseString!wchar; alias DString = BaseString!dchar; That works in this case. Other cases are different, eg: module libep.variant; public import libep.c.variant : Variant; That one works.
Jan 02
next sibling parent Rikki Cattermole <alphaglosined gmail.com> writes:
On 03/01/16 6:51 PM, Manu via Digitalmars-d wrote:
 On 3 January 2016 at 15:45, Manu <turkeyman gmail.com
 <mailto:turkeyman gmail.com>> wrote:

     On 3 January 2016 at 15:34, Rikki Cattermole via Digitalmars-d
     <digitalmars-d puremagic.com <mailto:digitalmars-d puremagic.com>>
     wrote:

         On 03/01/16 6:26 PM, Manu via Digitalmars-d wrote:

             On 3 January 2016 at 15:17, Rikki Cattermole via Digitalmars-d
             <digitalmars-d puremagic.com
             <mailto:digitalmars-d puremagic.com>
             <mailto:digitalmars-d puremagic.com
             <mailto:digitalmars-d puremagic.com>>> wrote:

                  Ok, so what I gathered from that is that if a D
             package/module
                  matches a C++ one in scope, D will only be checked.


             No, you name conflict error. But that's not the main problem
             I'm talking
             about, which is that namespace scopes are created and break
             everything.

                  The obvious answer would be to rename the D side, but
             that really
                  isn't good enough.


             You don't just go and rename an entire existing project,
             which is a lib
             in this case (so, also rename all the clients...?) because
             you need to
             type extern(C++) somewhere :/


         Hang on I just tried this on Windows:

         module ns.m;

         import x.y;
         // import x.y : ns.Y; // doesn't work grr
         import x.y : Y;


         module x.y;

         extern(C++, ns) {
                  struct Y {
                  }
         }


         Does this work for you?


     The short answer is, "most of the time".
     I've been using recursive modules to place extern(C++) declarations
     in a sensible scope quite a lot. It breaks sometimes, not sure
     why... suspect it's related to forward referencing, or
     multiple/semi-circular imports.


 For instance, connecting to the C++ string lib:

 module libep.string;
 public import libep.c.string : BaseString, MutableString, SharedString;
 alias String = BaseString!char;
 alias WString = BaseString!wchar;
 alias DString = BaseString!dchar;

 Those don't like to be imported that way: Error: template instance
 BaseString!char BaseString is not a template declaration, it is a alias
 If I instead:

 module libep.string;
 static import libep.c.string;
 alias BaseString = libep.c.string.BaseString;
 alias MutableString = libep.c.string.MutableString;
 alias SharedString = libep.c.string.SharedString;
 alias String = BaseString!char;
 alias WString = BaseString!wchar;
 alias DString = BaseString!dchar;

 That works in this case. Other cases are different, eg:

 module libep.variant;
 public import libep.c.variant : Variant;

 That one works.
Can you please come on IRC? It will be a little easier to solve this.
Jan 02
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/2/2016 9:51 PM, Manu via Digitalmars-d wrote:
 For instance, connecting to the C++ string lib:

 module libep.string;
 public import libep.c.string : BaseString, MutableString, SharedString;
 alias String = BaseString!char;
 alias WString = BaseString!wchar;
 alias DString = BaseString!dchar;

 Those don't like to be imported that way: Error: template instance
 BaseString!char BaseString is not a template declaration, it is a alias
Please file a bug report for that.
Jan 02
parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 3 January 2016 at 17:06, Walter Bright via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On 1/2/2016 9:51 PM, Manu via Digitalmars-d wrote:

 For instance, connecting to the C++ string lib:

 module libep.string;
 public import libep.c.string : BaseString, MutableString, SharedString;
 alias String = BaseString!char;
 alias WString = BaseString!wchar;
 alias DString = BaseString!dchar;

 Those don't like to be imported that way: Error: template instance
 BaseString!char BaseString is not a template declaration, it is a alias
Please file a bug report for that.
But it works in reduced test cases. I can't find a way to practically bug a lot of these sorts of problems without posting my source tree. I'll try and reduce this one again...
Jan 02
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/2/2016 11:17 PM, Manu via Digitalmars-d wrote:
 I'll try and reduce this one again...
Thanks, I appreciate the effort you're making. BTW, please tag all C++ related bug reports with the "C++" keyword in bugzilla.
Jan 03
parent Walter Bright <newshound2 digitalmars.com> writes:
On 1/3/2016 12:24 AM, Walter Bright wrote:
 On 1/2/2016 11:17 PM, Manu via Digitalmars-d wrote:
 I'll try and reduce this one again...
Thanks, I appreciate the effort you're making. BTW, please tag all C++ related bug reports with the "C++" keyword in bugzilla.
On second thought, I think you'll be wasting your time. The two bugzillas posted suggest to me where the problem lies, and there's no sense in you producing more bug reports for the same thing.
Jan 03
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2016-01-03 08:17, Manu via Digitalmars-d wrote:

 I'll try and reduce this one again...
Have you tried using dustmite [1] to reduce the code? It will automatically modify/reduce the source code as long as the issue persists. When it no longer can modify the source code while the issue still persist it's complete and you have a reduced test case. Hopefully small enough. The result is usually small enough that if you have proprietary code can rename the symbols, if necessary. [1] https://github.com/CyberShadow/DustMite -- /Jacob Carlborg
Jan 03
parent John Colvin <john.loughran.colvin gmail.com> writes:
On Sunday, 3 January 2016 at 14:50:51 UTC, Jacob Carlborg wrote:
 On 2016-01-03 08:17, Manu via Digitalmars-d wrote:

 I'll try and reduce this one again...
Have you tried using dustmite [1] to reduce the code? It will automatically modify/reduce the source code as long as the issue persists. When it no longer can modify the source code while the issue still persist it's complete and you have a reduced test case. Hopefully small enough. The result is usually small enough that if you have proprietary code can rename the symbols, if necessary. [1] https://github.com/CyberShadow/DustMite
it can obfuscate the output for you with --obfuscate
Jan 03
prev sibling parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 3 January 2016 at 15:34, Rikki Cattermole via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On 03/01/16 6:26 PM, Manu via Digitalmars-d wrote:

 On 3 January 2016 at 15:17, Rikki Cattermole via Digitalmars-d
 <digitalmars-d puremagic.com <mailto:digitalmars-d puremagic.com>> wrote:

     Ok, so what I gathered from that is that if a D package/module
     matches a C++ one in scope, D will only be checked.


 No, you name conflict error. But that's not the main problem I'm talking
 about, which is that namespace scopes are created and break everything.

     The obvious answer would be to rename the D side, but that really
     isn't good enough.


 You don't just go and rename an entire existing project, which is a lib
 in this case (so, also rename all the clients...?) because you need to
 type extern(C++) somewhere :/
Hang on I just tried this on Windows: module ns.m; import x.y; // import x.y : ns.Y; // doesn't work grr import x.y : Y; module x.y; extern(C++, ns) { struct Y { } } Does this work for you?
The short answer is, "most of the time". I've been using recursive modules to place extern(C++) declarations in a sensible scope quite a lot. It breaks sometimes, not sure why... suspect it's related to forward referencing, or multiple/semi-circular imports.
Jan 02
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
Your news software is double posting again (as text and again as html)
Jan 02
parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 3 January 2016 at 17:02, Walter Bright via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 Your news software is double posting again (as text and again as html)
I'm using gmail, the worlds single most popular mail client by a gigantic margin, with default settings. Fix the forum.
Jan 02
parent Walter Bright <newshound2 digitalmars.com> writes:
On 1/2/2016 11:34 PM, Manu via Digitalmars-d wrote:
 On 3 January 2016 at 17:02, Walter Bright via Digitalmars-d
 <digitalmars-d puremagic.com> wrote:
 Your news software is double posting again (as text and again as html)
I'm using gmail, the worlds single most popular mail client by a gigantic margin, with default settings. Fix the forum.
The forum cannot fix what is sent to it. The forum does display your posts (it ignores the html section). The problem is simply that the accumulating size means bandwidth and slower speed for everyone. There's probably some setting in gmail to turn off embedded html.
Jan 03
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/2/2016 9:45 PM, Manu via Digitalmars-d wrote:
 I've been using recursive modules to place extern(C++) declarations in a
 sensible scope quite a lot. It breaks sometimes, not sure why... suspect it's
 related to forward referencing, or multiple/semi-circular imports.
It's a bug if circular imports do not work. But circular imports are not allowed in Go, and I consider them as something to avoid. They can be very confusing to try and follow.
Jan 02
next sibling parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 3 January 2016 at 17:04, Walter Bright via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On 1/2/2016 9:45 PM, Manu via Digitalmars-d wrote:

 I've been using recursive modules to place extern(C++) declarations in a
 sensible scope quite a lot. It breaks sometimes, not sure why... suspect
 it's
 related to forward referencing, or multiple/semi-circular imports.
It's a bug if circular imports do not work. But circular imports are not allowed in Go, and I consider them as something to avoid. They can be very confusing to try and follow.
This is why I talk about 'real-world' code, it's never that simple. String for instance, there are a lot of string functions; it depends on lots of stuff, and basically everything depends on string. Examples of circular references like this are endless, and they're usually foundational things, at the bottom of the stack.
Jan 02
parent Walter Bright <newshound2 digitalmars.com> writes:
On 1/2/2016 11:29 PM, Manu via Digitalmars-d wrote:
 This is why I talk about 'real-world' code, it's never that simple. String for
 instance, there are a lot of string functions; it depends on lots of stuff, and
 basically everything depends on string. Examples of circular references like
 this are endless, and they're usually foundational things, at the bottom of the
 stack.
Circular declarations are one thing, circular modules are another. Phobos suffers from circular modules, and I'd like to refactor them out.
Jan 03
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2016-01-03 08:04, Walter Bright wrote:

 It's a bug if circular imports do not work. But circular imports are not
 allowed in Go, and I consider them as something to avoid. They can be
 very confusing to try and follow.
Either they're supported and should work every single time or they shouldn't be supported at all. Supported anything in between is just messy. -- /Jacob Carlborg
Jan 03
parent Walter Bright <newshound2 digitalmars.com> writes:
On 1/3/2016 6:45 AM, Jacob Carlborg wrote:
 On 2016-01-03 08:04, Walter Bright wrote:

 It's a bug if circular imports do not work. But circular imports are not
 allowed in Go, and I consider them as something to avoid. They can be
 very confusing to try and follow.
Either they're supported and should work every single time or they shouldn't be supported at all. Supported anything in between is just messy.
I agree. But I still think that having circular imports is indicative of improper abstraction/encapsulation.
Jan 03
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/2/2016 8:54 PM, Manu via Digitalmars-d wrote:
 C++ namespacing is causing me endless, and I mean *endless* trouble.
 This idea that we express the C++ namespace hierarchy in D is the main problem.
 I don't think C++ namespaces should interfere with D scoping rules, they should
 be purely for mangling.
 It creates a whole bundle of edge cases which either don't have work arounds,
or
 REALLY awkward workarounds which typically have a heavy impact on all the
 regular D code that the C++ code interacts with.

 Not least of which is that C++ namespaces usually span the entire project, and
 in D a C++ namespace can only appear in one module ever.
 Declaring symbols with the same C++ namespace in different modules leads to
 multiple definition errors, and if you are super-careful to avoid those, you
 gain name resolution issues in it's place.
That works the same as in C++. Don't define the same symbol in the same C++ namespace in multiple modules. It doesn't work in C++, and doesn't work in D for exactly the same reason.
 It is also very awkward that a C++ namespace can't be the same as a top level
 package name. My top level package is named the same as one of my C++
 namespaces... what do I do? It gets ugly real fast.

 The main problem extends from this situation:

 module x.y;

 extern(C++, ns) struct Y {}


 module ns.m;

 import x.y; // fail, the c++ namespace is already present (top level module)
Doesn't fail when I try it.
 import x.y : ns.Y; // fail, '.' can't appear here
Right, this syntax only works for module scope declarations. Y is not module scope. You can do: import x.y : ns;
 import x.y : Y; // fail, not found
Again, Y is not module scope.
 // This **sometimes** works,
sometimes?
 and it's very brittle
??
 static import x.y;
 alias Y = x.y.Y;
Nothing wrong with that.
 Thing is, I'm not declaring a C++ object, I'm declaring a D object,  the only
 thing being that struct's take care to maintain common binary layout, and
 functions just mangle like C++ so that my code links. I'm in D, I'm declaring
my
 stuff in the D module where it should be scoped, and where other D code should
 expect to find it. I don't see any point in building the C++ hierarchy in this
 space. C++ namespace rules are incompatible with D; you can litter them through
 C++ code, and add new symbols to C++ namespaces from anywhere...
You can do that in D as well, as long as you follow the One Definition Rule, which you have to with C++ code anyway.
 this is
 fundamentally incompatible with D, and no further reasoning should be required
 to conclude that it can't be reproduced, so it should be for mangling purposes
only.
I guarantee you that if we'd implemented it that way, you'd have a long litany of complaints about that, because the compiler could not distinguish Y from ns.Y.
 I have spent **days**, actually, weeks of my free time trying to make my tiny
 bit of code build, and it's just nothing but trouble after trouble. I have
 completely restructured my code at least 3 times to try and find a way to make
 it fit together in a way that's both practical and works, but I just can't. It
 always hits some brick wall somewhere.

 extern(C++, NS) looks okay in isolated tests/experiments, but try and actually
 use it, and you will become very frustrated.

 Please, fix this. I'm almost done. I'm really struggling to keep this dream
alive.
I do not understand what difficulty you are having with this.
Jan 02
next sibling parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 3 January 2016 at 15:40, Walter Bright via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On 1/2/2016 8:54 PM, Manu via Digitalmars-d wrote:

 C++ namespacing is causing me endless, and I mean *endless* trouble.
 This idea that we express the C++ namespace hierarchy in D is the main
 problem.
 I don't think C++ namespaces should interfere with D scoping rules, they
 should
 be purely for mangling.
 It creates a whole bundle of edge cases which either don't have work
 arounds, or
 REALLY awkward workarounds which typically have a heavy impact on all the
 regular D code that the C++ code interacts with.

 Not least of which is that C++ namespaces usually span the entire
 project, and
 in D a C++ namespace can only appear in one module ever.
 Declaring symbols with the same C++ namespace in different modules leads
 to
 multiple definition errors, and if you are super-careful to avoid those,
 you
 gain name resolution issues in it's place.
That works the same as in C++. Don't define the same symbol in the same C++ namespace in multiple modules. It doesn't work in C++, and doesn't work in D for exactly the same reason.
I'm not defining the same symbols, I'm defining different symbols, just inside the same namespace. It is also very awkward that a C++ namespace can't be the same as a top
 level
 package name. My top level package is named the same as one of my C++
 namespaces... what do I do? It gets ugly real fast.

 The main problem extends from this situation:

 module x.y;

 extern(C++, ns) struct Y {}


 module ns.m;

 import x.y; // fail, the c++ namespace is already present (top level
 module)
Doesn't fail when I try it.
Import another module with the same namespace, have the objects within each instance of the namespace refer to eachother. import x.y : Y; // fail, not found

 Again, Y is not module scope.

 // This **sometimes** works,

 sometimes?
Yes, it works sometimes. and it's very brittle

 ??
It only 'sometimes' works. Reasons are not clear. static import x.y;
 alias Y = x.y.Y;
Nothing wrong with that.
Except that it doesn't always work. It also implies that I must double the number of modules I have, so that I can wrap every module with a C++ namespace in an outer one without it. Thing is, I'm not declaring a C++ object, I'm declaring a D object, the
 only
 thing being that struct's take care to maintain common binary layout, and
 functions just mangle like C++ so that my code links. I'm in D, I'm
 declaring my
 stuff in the D module where it should be scoped, and where other D code
 should
 expect to find it. I don't see any point in building the C++ hierarchy in
 this
 space. C++ namespace rules are incompatible with D; you can litter them
 through
 C++ code, and add new symbols to C++ namespaces from anywhere...
You can do that in D as well, as long as you follow the One Definition Rule, which you have to with C++ code anyway.
It doesn't scale though. module x.x; import x.y; extern(C++, ns) { class X { Y y; } } module x.y; import x.x; extern(C++, ns) { class Y { X x; } } Error: undefined identifier 'Y' this is
 fundamentally incompatible with D, and no further reasoning should be
 required
 to conclude that it can't be reproduced, so it should be for mangling
 purposes only.
I guarantee you that if we'd implemented it that way, you'd have a long litany of complaints about that, because the compiler could not distinguish Y from ns.Y.
You would put it in its own module like normal D code, and let normal D symbol resolution take care of it. That's surely the preferred approach anyway? Chances are, your D module structure will match the C++ module structure verbatim anyway, which will have already been structured that way. I have spent **days**, actually, weeks of my free time trying to make my
 tiny
 bit of code build, and it's just nothing but trouble after trouble. I have
 completely restructured my code at least 3 times to try and find a way to
 make
 it fit together in a way that's both practical and works, but I just
 can't. It
 always hits some brick wall somewhere.

 extern(C++, NS) looks okay in isolated tests/experiments, but try and
 actually
 use it, and you will become very frustrated.

 Please, fix this. I'm almost done. I'm really struggling to keep this
 dream alive.
I do not understand what difficulty you are having with this.
It's endlessly difficult, and it's really hard to summarise. I'm telling you this; as someone who's endlessly fought with this in practical real-world applications, the design is wrong. D has module scoping, it works, let D's scoping do it's job. This design can lead to nothing but edge cases. We have plenty of edges already. There was a binary decision made; as far as I know, the decision was made on a whim, there was no design committee, a decision was simply chosen. I know of no argument that demonstrates that the current state is correct, but I have months of wasted time and energy that prove that it's wrong. Why do I need to now take even more time to construct an elaborate suite of examples to demonstrate my argument? I can't get work done. I've spent all the free time I have trying, and I'd rather write code than spend my time reducing test cases. Try and bind to a reasonably complex C++ project and you will discover the same thing... or don't, I've honestly already done that work for you! Please don't make me waste endlessly more of my time, I don't have energy left to spare. This is precisely what's driving me away from D. I can't take it anymore, everything hits brick walls, I am so frustrated, I just want to have a **SINGLE** win, where I can complete a single real-world project and say I have written something that works! If you're not convinced, then start by fixing the forward referencing issues. They are just bugs, and I highly suspect that many of my tests and experiments have been hindered by the fact that there are actually 2-3 issues working here in tandem. The error messages all look basically the same and offer no help. Forward referencing issue == "undefined identifier", namespace conflict == "undefined identifier". I suspect that cases exist where I was testing one thing, and the other thing jumped in and caused a mis-diagnosis. That doesn't mean it's not wrong though... let the D module system do what it's designed to do. The point of extern(C++) is to present a C++ API to a D user, so it needs to be arranged in D's terms or the user will feel very uncomfortable, and the author will have to jump through more hoops than if they just stuck with C++.
Jan 02
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/2/2016 10:39 PM, Manu via Digitalmars-d wrote:
 On 3 January 2016 at 15:40, Walter Bright via Digitalmars-d
 <digitalmars-d puremagic.com <mailto:digitalmars-d puremagic.com>> wrote:

     On 1/2/2016 8:54 PM, Manu via Digitalmars-d wrote:

         C++ namespacing is causing me endless, and I mean *endless* trouble.
         This idea that we express the C++ namespace hierarchy in D is the main
         problem.
         I don't think C++ namespaces should interfere with D scoping rules,
they
         should
         be purely for mangling.
         It creates a whole bundle of edge cases which either don't have work
         arounds, or
         REALLY awkward workarounds which typically have a heavy impact on all
the
         regular D code that the C++ code interacts with.

         Not least of which is that C++ namespaces usually span the entire
         project, and
         in D a C++ namespace can only appear in one module ever.
         Declaring symbols with the same C++ namespace in different modules
leads to
         multiple definition errors, and if you are super-careful to avoid
those, you
         gain name resolution issues in it's place.


     That works the same as in C++. Don't define the same symbol in the same C++
     namespace in multiple modules. It doesn't work in C++, and doesn't work in
D
     for exactly the same reason.

 I'm not defining the same symbols, I'm defining different symbols, just inside
 the same namespace.
Then how do they wind up with the same mangled name? Please give an example.
         The main problem extends from this situation:

         module x.y;

         extern(C++, ns) struct Y {}


         module ns.m;

         import x.y; // fail, the c++ namespace is already present (top level
module)

     Doesn't fail when I try it.

 Import another module with the same namespace, have the objects within each
 instance of the namespace refer to eachother.
You'll have to post an example.
         static import x.y;
         alias Y = x.y.Y;
      Nothing wrong with that.
 Except that it doesn't always work.
I can't help with statements like "not always", "seems to", "sometimes", etc.
 It also implies that I must double the number of modules I have, so that I can
 wrap every module with a C++ namespace in an outer one without it.
I have no idea why you must do that.
     You can do that in D as well, as long as you follow the One Definition
Rule,
     which you have to with C++ code anyway.


 It doesn't scale though.

 module x.x;
 import x.y;

 extern(C++, ns)
 {
    class X { Y y; }
 }


 module x.y;
 import x.x;
 extern(C++, ns)
 {
    class Y { X x; }
 }


 Error: undefined identifier 'Y'
First off, please do not write code like that. If you find yourself doing such routinely, AAAAIIIIEEEEEE !!!! :-) I understand that people can and will write code like that, and I will try and help you get it to work anyway. Secondly, it points out a misunderstanding of how namespace lookup works in D. Namespaces in D: 1. follow D lookup rules 2. follow C++ mangling rules The example of: Y y; is clearly assuming that C++ namespace lookup rules are being followed. They are not, D lookup rules are. Y is declared in x.y.ns, not x.x.ns. As far as the compiler is concerned, x.y.ns and x.x.ns are different namespaces (although they will mangle the same). Thus, "Y" should be "x.y.ns.Y". You can see this if you replace "extern(C++, ns)" with "struct ns". You'll get the SAME error message! The following should work, according to the scoping rules: -----------x.d------------ import y; //struct ns extern (C++, ns) { class X { y.ns.Y a; } } ----------y.d------------ import x; //struct ns extern (C++, ns) { class Y { x.ns.X b; } } It does work if the struct is used. This illustrates how symbol lookup works. I don't know why that example doesn't work, but have filed: https://issues.dlang.org/show_bug.cgi?id=15503 because it should work (it works when 'struct' is used, and the name lookup should be the same).
 You would put it in its own module like normal D code, and let normal D symbol
 resolution take care of it.
 That's surely the preferred approach anyway? Chances are, your D module
 structure will match the C++ module structure verbatim anyway, which will have
 already been structured that way.
C++ doesn't have a module structure, and the way you propose cannot work in D, since D does not have a global scope. If I implemented your method, the first bug report from you will be: --- int x; extern (C++, ns) { char x; } --- error: multiple definition of x You'll say "but it is in a different namespace, so I should be able to declare another x!" and you would be right. It will also be impossible to connect to C++ code that defines the same identifier in different namespaces.
 It's endlessly difficult, and it's really hard to summarise.
I don't need a summary, I need specific cases.
 There was a binary decision made; as far as I know, the decision was made on a
 whim, there was no design committee, a decision was simply chosen.
 I know of no argument that demonstrates that the current state is correct, but
I
 have months of wasted time and energy that prove that it's wrong. Why do I need
 to now take even more time to construct an elaborate suite of examples to
 demonstrate my argument?
Producing cases that fail should have been a byproduct of the production of code that failed. In any case, without examples that illustrate the problem(s) you're having, I cannot help.
 I can't get work done. I've spent all the free time I have trying, and I'd
 rather write code than spend my time reducing test cases.
 Try and bind to a reasonably complex C++ project and you will discover the same
 thing... or don't, I've honestly already done that work for you!
I appreciate that you've done the work for me, but I'd have to start over from scratch because you don't provide examples that don't work, and I'd have to guess what you were trying to do, which never works out very well.
 Please don't make me waste endlessly more of my time, I don't have energy left
 to spare. This is precisely what's driving me away from D. I can't take it
 anymore, everything hits brick walls, I am so frustrated, I just want to have a
 **SINGLE** win, where I can complete a single real-world project and say I have
 written something that works!
I hope that you'll come here and ask for help before you've expended endless hours beating your head :-(
 If you're not convinced, then start by fixing the forward referencing issues.
I don't know of any bugzilla issues with that.
Jan 03
parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 3 January 2016 at 18:03, Walter Bright via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 C++ doesn't have a module structure,
It's called the filesystem ;) .. People use folders and filenames to describe what would be 'modules' in C, if C was said to have modules. Sometimes they make namespaces that match the filesystem ;)
 and the way you propose cannot work in
 D, since D does not have a global scope. If I implemented your method, the
 first bug report from you will be:

     ---
     int x;
     extern (C++, ns) { char x; }
     ---
     error: multiple definition of x
This!!! You're on to it!! That's exactly what I want; I ***REALLLY*** want the compiler to emit that error message in that exact situation! Please, please can we have that? :)
 You'll say "but it is in a different namespace, so I should be able to
 declare another x!" and you would be right.
No. No I wouldn't! They're both symbols with the same name in the same scope! extern(C++) means nothing, it should just change how it mangles. Let the D module system handle symbol lookup as usual. I want the error message you said above.
 It will also be impossible to
 connect to C++ code that defines the same identifier in different
 namespaces.
...put it in a different module? Just like any normal D code. ---- ns1.cpp ---- namespace ns1 { int identifier; } ---- ns2.cpp ---- namespace ns2 { int identifier; } ---- ns1.d ---- module ns1; extern(C++, ns1) int identifier; ---- ns2.d ---- module ns2; extern(C++, ns2) int identifier; It's beautiful! This would solve a lot of awkward issues. Also consider that my top level package has the same name as the C++ namespace. That's really awkward, and I also anticipate this would be the common case (why would the qt package be called anything other than 'qt'? sadly, this matches the C++ namespace) Oh yeah, I just remembered another great case, I had this in C++: namespace delegate {} 'delegate' is not a valid identifier in D, I was going to come in here and bang the drum again, and also suggest that the namespace needs to be a string, ie extern(C++, "delegate") D takes a lot more names from the namespace than C++ does. The user has _no control_ over what they name the C++ namespace; by definition, it already exists. It's for binding purposes. It might not even be a name that's a valid D identifier. It's just for mangling.
 There was a binary decision made; as far as I know, the decision was made
 on a
 whim, there was no design committee, a decision was simply chosen.
 I know of no argument that demonstrates that the current state is correct,
 but I
 have months of wasted time and energy that prove that it's wrong. Why do I
 need
 to now take even more time to construct an elaborate suite of examples to
 demonstrate my argument?
Producing cases that fail should have been a byproduct of the production of code that failed. In any case, without examples that illustrate the problem(s) you're having, I cannot help.
It's I can't reasonably zip the project and email it 100 times a day. I'd need to involve management the moment I wanted to do that. These problems emerge in non-trivial situations.
 I can't get work done. I've spent all the free time I have trying, and I'd
 rather write code than spend my time reducing test cases.
 Try and bind to a reasonably complex C++ project and you will discover the
 same
 thing... or don't, I've honestly already done that work for you!
I appreciate that you've done the work for me, but I'd have to start over from scratch because you don't provide examples that don't work, and I'd have to guess what you were trying to do, which never works out very well.
I don't own the code I write >_< This is an eternal problem of mine. This project is 30 files, almost all of them have extern(C++) in them, and they interact... It's extremely difficult and time consuming to reduce. I suspect the forward referencing issues may be flagging false positives when I'm debugging, that should be first. But this namespace thing is the cause of problems at scale.
 Please don't make me waste endlessly more of my time, I don't have energy
 left
 to spare. This is precisely what's driving me away from D. I can't take it
 anymore, everything hits brick walls, I am so frustrated, I just want to
 have a
 **SINGLE** win, where I can complete a single real-world project and say I
 have
 written something that works!
I hope that you'll come here and ask for help before you've expended endless hours beating your head :-(
This isn't the first time I've had this rant ;) But this is it, please help me get this C++ binding working. I already anticipate a new class of error emerging as soon as I can reach a state where foundational stuff isn't causing me grief... One involves more complex inheritence; we have typical C++ 'interfaces', ie, classes populated only with abstract virtuals, and multiple inheritence of those. Does extern(C++) currently support inheriting multiple interfaces? I also expect I'll need a way to express a class instance. I noticed that in: extern(C++) { class C {} struct S(T) {} } S!C x; I noticed in one case like this that 'x' seemed to mangle as C++ S<C*>, where the '*' in the mangled name seems to be implicit in D (presumably because D's classes are always references?). If that is indeed the case, we'll need a way to express a symbol name that is just the instance 'C', not 'C*'. But these will be advanced problems, with possible work-arounds when basic problems are solved. I was pondering a solution for class instances like: struct ByVal(C) if(is(C == class)) { alias get this; // magic to stitch up constructors and stuff private: void[__traits(classInstanceSize, C)] instance; property C get() { return cast(C)instance.ptr; } } Something like that would express C++ style class aggregation... Is there something like that in the std library? If so, it should be special-cased so that extern(C++) will mangle it as C rather than the usual C*. S!(ByVal!C) x; // -> S<C>, instead of S<ByVal<C*>>
Jan 03
next sibling parent Daniel N <ufo orbiting.us> writes:
On Sunday, 3 January 2016 at 11:25:37 UTC, Manu wrote:
 This!!! You're on to it!!
 That's exactly what I want; I ***REALLLY*** want the compiler 
 to emit
 that error message in that exact situation!
 Please, please can we have that? :)
QFT if only we had access to some lowlevel primitive which facilitated this, it's much easier to add a scope when needed than to remove an unwanted scope. :/
Jan 03
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/3/2016 3:25 AM, Manu via Digitalmars-d wrote:
 On 3 January 2016 at 18:03, Walter Bright via Digitalmars-d
 <digitalmars-d puremagic.com> wrote:
 C++ doesn't have a module structure,
It's called the filesystem ;) .. People use folders and filenames to describe what would be 'modules' in C, if C was said to have modules. Sometimes they make namespaces that match the filesystem ;)
I know how C++ name scoping works, after all, I implemented a C++ compiler. C++ doesn't have modules, and doesn't even have a semantic notion of files. You can pretend it has them, but when you talk about "edge cases not working", they aren't going to work in spades here.
 and the way you propose cannot work in
 D, since D does not have a global scope. If I implemented your method, the
 first bug report from you will be:

      ---
      int x;
      extern (C++, ns) { char x; }
      ---
      error: multiple definition of x
This!!! You're on to it!! That's exactly what I want; I ***REALLLY*** want the compiler to emit that error message in that exact situation! Please, please can we have that? :)
No. If D is to support C++ namespaces, it has to support declaring the same identifier for different purposes in different namespaces. C++ namespaces have different scopes in C++. Doing anything else would make it impossible to connect to perfectly legitimate C++ programs. The WHOLE POINT of C++ namespaces is to support declaring the same identifier in different namespaces.
 This would solve a lot of awkward issues.
It'd be a river of bug reports, because sure as shootin', people are going to try to interface to this C++ code: namespace ns1 { int identifier; } namespace ns2 { int identifier; } And why shouldn't they? It's correct and legitimate C++ code.
 Oh yeah, I just remembered another great case, I had this in C++:
    namespace delegate {}
 'delegate' is not a valid identifier in D, I was going to come in here
 and bang the drum again, and also suggest that the namespace needs to
 be a string, ie extern(C++, "delegate")
 D takes a lot more names from the namespace than C++ does.

 The user has _no control_ over what they name the C++ namespace; by
 definition, it already exists. It's for binding purposes. It might not
 even be a name that's a valid D identifier.
 It's just for mangling.
Please file an enhancement request for that. Though you can probably make it work by writing a C++ wrapper for it.
 But this is it, please help me get this C++ binding working.
The 2 bugzilla issues filed already are enough to make progress with. You needn't do anything more on this at the moment.
 One involves more complex inheritence; we have typical C++
 'interfaces', ie, classes populated only with abstract virtuals, and
 multiple inheritence of those. Does extern(C++) currently support
 inheriting multiple interfaces?
Only if they have no fields, i.e. they mirror COM inheritance.
 I also expect I'll need a way to express a class instance. I noticed that in:

 extern(C++)
 {
    class C {}
    struct S(T) {}
 }
 S!C x;

 I noticed in one case like this that 'x' seemed to mangle as C++
 S<C*>, where the '*' in the mangled name seems to be implicit in D
 (presumably because D's classes are always references?).
 If that is indeed the case, we'll need a way to express a symbol name
 that is just the instance 'C', not 'C*'. But these will be advanced
 problems, with possible work-arounds when basic problems are solved.
D doesn't support "Shimmer" aggregates ("Is it a floor wax or a dessert topping?") You may need to write C++ wrappers for the problematic C++ types, and then interface to the wrappers.
Jan 03
next sibling parent reply Marc =?UTF-8?B?U2Now7x0eg==?= <schuetzm gmx.net> writes:
On Sunday, 3 January 2016 at 16:18:13 UTC, Walter Bright wrote:
 No. If D is to support C++ namespaces, it has to support 
 declaring the same identifier for different purposes in 
 different namespaces. C++ namespaces have different scopes in 
 C++. Doing anything else would make it impossible to connect to 
 perfectly legitimate C++ programs. The WHOLE POINT of C++ 
 namespaces is to support declaring the same identifier in 
 different namespaces.
Yes, but the point of `extern(C++, ns)` is NOT to achieve the same in D! D has its own mechanisms for that, primarily the module system, as well as hacks like static structs. And I don't see how Manu's suggestion would make it impossible to link to some C++ programs. Can you give an example?
 This would solve a lot of awkward issues.
It'd be a river of bug reports, because sure as shootin', people are going to try to interface to this C++ code: namespace ns1 { int identifier; } namespace ns2 { int identifier; } And why shouldn't they? It's correct and legitimate C++ code.
I guess in reality this would not be a frequent thing. Most real C++ code will have both instances of `identifier` declared in different header files, and D's modules will usually closely mirror those, so they will end up in different modules on the D side. In the rare case the same identifier actually does appear twice in the same module, static structs can be used: struct ns1 { extern(C++, ns1): int identifier; } struct ns2 { extern(C++, ns2): int identifier; }
Jan 03
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/3/2016 9:14 AM, Marc Schütz wrote:
 On Sunday, 3 January 2016 at 16:18:13 UTC, Walter Bright wrote:
 No. If D is to support C++ namespaces, it has to support declaring the same
 identifier for different purposes in different namespaces. C++ namespaces have
 different scopes in C++. Doing anything else would make it impossible to
 connect to perfectly legitimate C++ programs. The WHOLE POINT of C++
 namespaces is to support declaring the same identifier in different namespaces.
Yes, but the point of `extern(C++, ns)` is NOT to achieve the same in D! D has its own mechanisms for that, primarily the module system, as well as hacks like static structs. And I don't see how Manu's suggestion would make it impossible to link to some C++ programs. Can you give an example?
I did. You quoted it below :-)
 This would solve a lot of awkward issues.
It'd be a river of bug reports, because sure as shootin', people are going to try to interface to this C++ code: namespace ns1 { int identifier; } namespace ns2 { int identifier; } And why shouldn't they? It's correct and legitimate C++ code.
I guess in reality this would not be a frequent thing. Most real C++ code will have both instances of `identifier` declared in different header files, and D's modules will usually closely mirror those, so they will end up in different modules on the D side.
My experience with "who would ever write such code" is they exist and you cannot wish them away. In a more general case, we should allow as much C++ compatibility as we can, because every shortcoming will be complained about at length. And, as Manu pointed out, one is often not able to adjust the C++ side of the bridge. Besides, this isn't even an edge case. It's what C++ namespaces are for.
 In the rare case
That's a vast assumption. Manu is one programmer out of a million.
 the same identifier actually does appear twice in the same
 module, static structs can be used:

 struct ns1 {
      extern(C++, ns1):
      int identifier;
 }
 struct ns2 {
      extern(C++, ns2):
      int identifier;
 }
Offhand, I can't think at the moment why that wouldn't work, but using structs as C++ namespaces did have problems I don't recall at the moment, and: 1. It's ugly. 2. You're an expert, and it's wrong - the fields need to be 'static'. How will others fare? 3. I suspect that this ugly thing will become "best practice", and we won't be able to fix it in a backwards compatible way. 4. Structs carry other baggage with them, such as 'init' fields, TypeInfo's, default member functions, etc. 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.
Jan 03
next sibling parent Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 4 January 2016 at 03:53, Walter Bright via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 1/3/2016 9:14 AM, Marc Schütz wrote:
 I guess in reality this would not be a frequent thing. Most real C++ code
 will
 have both instances of `identifier` declared in different header files,
 and D's
 modules will usually closely mirror those, so they will end up in
 different
 modules on the D side.
My experience with "who would ever write such code" is they exist and you cannot wish them away.
There's nothing wrong with it if they do, they can easily address the situation, and they would almost certainly do so by default as they naturally structure the API into modules.
 In a more general case, we should allow as much C++
 compatibility as we can, because every shortcoming will be complained about
 at length. And, as Manu pointed out, one is often not able to adjust the C++
 side of the bridge.
How would this ever lead to adjustment of the C++ code in any case? That's not an issue here. We're going to mangle the appropriate C++ symbol either way, what we're discussing is purely about the D code, and not making it awkward for the D users. It's not a 'shortcoming' to let the D coder lay out their modules how they want to, that's normal expected behaviour. Anything that inhibits the ability to organise your D code is a shortcoming, and this behaviour is the biggest shortcoming of the extern(C++) experience by far. It's cause for a bunch of really awkward problems, and it's completely pointless; we have modules! This behaviour inhibits C++ namespaces with the same name as the top level D package (surely this is the 99% _expected_ case), and it also needlessly reduces the pool of compatible namespaces to valid D identifiers; a pointless restriction. You're arguing for "as much C++ compatibility as we can", while arguing for something that does nothing but inhibit C++ compatibility, make it needlessly painful for the D lib coder, and surprising and unconventional to the end-user... this is Schrodinger's argument. This decision impacts _every_ extern(C++) definition everywhere! They all need to be aliased around into the appropriate locations where they should have been defined in the first place. That's messy, hard to follow, hard to explain, and hard to maintain. Also the risk of 'invalid' C++ namespace names, which is an absurd problem to have, only possible under this design since every C++ namespace name must also be a valid D identifier, is much greater than your hypothetical non-problem case. I have already run into this multiple times. I am demonstrating legitimate real-world problems with the design, and you hold fast to a broken design, because it protects against a single hypothetical 'problem' with a trivial and natural solution. I don't understand how it's possible to hold an objective resistance to this change.
 the same identifier actually does appear twice in the same
 module, static structs can be used:

 struct ns1 {
      extern(C++, ns1):
      int identifier;
 }
 struct ns2 {
      extern(C++, ns2):
      int identifier;
 }
Offhand, I can't think at the moment why that wouldn't work, but using structs as C++ namespaces did have problems I don't recall at the moment, and: 1. It's ugly. 2. You're an expert, and it's wrong - the fields need to be 'static'. How will others fare? 3. I suspect that this ugly thing will become "best practice", and we won't be able to fix it in a backwards compatible way.
'Best practice' would be to make another module. It's not so much 'best practice' as, 'normal D behaviour'.
 4. Structs carry other baggage with them, such as 'init' fields, TypeInfo's,
 default member functions, etc.
No structs, just make another module! >_< .. that's what they're for, that's how you do it in D!
 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.
Because we're not writing C++ code, we're writing D code, and any deviation from normal D behaviour should surely be taken as weird and unexpected. The fact that the lib was compiled from C++ code is uninteresting, irrelevant, and possibly even unknown to the library user. As far as they know, they're using a D lib, with an API presented to them in D's terms. That's the point of writing bindings. Almost all the quality D bindings I've ever used have made adaptations to present nicely for D use, and extern(C++) is no different; the binding author will organise their D modules in a sensible and logical manner wrt the api. C libs are small and flat enough that they can sometimes get away with direct 'machine' translation, but a good C++ binding will almost certainly require some care by the binding author to make it work nicely with D semantics, and feel natural to D users. This hypothetical problem you're attached to will tend to iron out naturally, and even if not, the workaround is trivial; put it in another module. The effect of which is exactly the same as the scope created by extern(C++) currently, but it's well understood by conforming to all existing rules, and as a bonus, every single problem I've complained about is instantly resolved, and enhancement requests like supporting "import x.y : X = ns.X;" become redundant. I'll add this, if I can't make the D bindings feel nice to use (which is very hard as it is now), that will significantly reduce motivation to USE said D bindings. If the bindings are riddled with awkwardness, why would anyone prefer them to the C++ bindings? The entire point of writing D bindings is to offer a superior experience using the library. If I fail to attain that goal, then *the whole point* of my effort is moot, and we will remain C++ users. I'm doing this, after-hours, as an avenue to give people in my office an opportunity to write some production D code as plugin to one of our major products, and maybe even ship something! Likewise, even if I wrangle it into something nice at the front-end despite this issue, if the binding itself appears to have been archaic and awkward to implement and maintain, that will equally make a terrible impression on the squad of engineers who will critique this code, and I will not be able to explain or defend this decision to them.
Jan 04
prev sibling next sibling parent Marc =?UTF-8?B?U2Now7x0eg==?= <schuetzm gmx.net> writes:
On Sunday, 3 January 2016 at 17:53:38 UTC, Walter Bright wrote:
 On 1/3/2016 9:14 AM, Marc Schütz wrote:
 On Sunday, 3 January 2016 at 16:18:13 UTC, Walter Bright wrote:
 No. If D is to support C++ namespaces, it has to support 
 declaring the same
 identifier for different purposes in different namespaces. 
 C++ namespaces have
 different scopes in C++. Doing anything else would make it 
 impossible to
 connect to perfectly legitimate C++ programs. The WHOLE POINT 
 of C++
 namespaces is to support declaring the same identifier in 
 different namespaces.
Yes, but the point of `extern(C++, ns)` is NOT to achieve the same in D! D has its own mechanisms for that, primarily the module system, as well as hacks like static structs. And I don't see how Manu's suggestion would make it impossible to link to some C++ programs. Can you give an example?
I did. You quoted it below :-)
But this is evidently not an example where it's "impossible to connect to perfectly legitimate C++ programs", because there are at least two practical ways to do so: 1) using the static struct hack, and 2) placing the symbols into separate modules.
   namespace ns1 { int identifier; }
   namespace ns2 { int identifier; }

 And why shouldn't they? It's correct and legitimate C++ code.
I guess in reality this would not be a frequent thing. Most real C++ code will have both instances of `identifier` declared in different header files, and D's modules will usually closely mirror those, so they will end up in different modules on the D side.
My experience with "who would ever write such code" is they exist and you cannot wish them away. In a more general case, we should allow as much C++ compatibility as we can, because every shortcoming will be complained about at length. And, as Manu pointed out, one is often not able to adjust the C++ side of the bridge. Besides, this isn't even an edge case. It's what C++ namespaces are for.
I don't agree with this. Their primary purpose is to avoid name collisions between symbols from different projects (or parts of a project), or to establish a symbol hierarchy independent from the source tree layout, but not to allow the same symbol several times in the same header file. That may happen in a few cases as a side effect, but I wouldn't say that's what they are made for.
 In the rare case
That's a vast assumption. Manu is one programmer out of a million.
Indeed I don't have statistics, but I think it's a reasonable assumption. We're talking about a very specific case here: that one C++ header declares symbols in several parallel (non-nested) namespaces. This is the only way the kinds of collision described by you can appear, if we stick to a 1:1 mapping between C++ headers and D modules. Do you have any real-world examples of that? I looked at several large C++ projects on Github, but couldn't find a single instance.
 Offhand, I can't think at the moment why that wouldn't work, 
 but using structs as C++ namespaces did have problems I don't 
 recall at the moment, and:

 1. It's ugly.
 2. You're an expert, and it's wrong - the fields need to be 
 'static'. How will others fare?
Yeah, my bad. But note that it's easy to recognize that mistake: it will fail to compile the first time you try to access one of the members.
 3. I suspect that this ugly thing will become "best practice", 
 and we won't be able to fix it in a backwards compatible way.
I merely wanted to show that there is a workaround if you absolutely need them to be declared in the same module. As Manu suggested, the usual and recommended way to handle this situation would be to put them in separate modules, along with other symbols in that namespace, no matter in which header file they are declared.
 4. Structs carry other baggage with them, such as 'init' 
 fields, TypeInfo's, default member functions, etc.
 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.
It is an unexpected behaviour for `extern`: neither `extern(C)`, `extern(D)`, `extern(C++)`, `extern(Objective-C)`, nor any other affect scoping or symbol lookup, only mangling and calling convention.
Jan 04
prev sibling parent reply Carl Sturtivant <sturtivant gmail.com> writes:
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.
Jan 05
parent Carl Sturtivant <sturtivant gmail.com> writes:
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!
Jan 06
prev sibling parent Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 4 January 2016 at 02:18, Walter Bright via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 1/3/2016 3:25 AM, Manu via Digitalmars-d wrote:
 On 3 January 2016 at 18:03, Walter Bright via Digitalmars-d
 <digitalmars-d puremagic.com> wrote:
 C++ doesn't have a module structure,
It's called the filesystem ;) .. People use folders and filenames to describe what would be 'modules' in C, if C was said to have modules. Sometimes they make namespaces that match the filesystem ;)
I know how C++ name scoping works, after all, I implemented a C++ compiler. C++ doesn't have modules, and doesn't even have a semantic notion of files. You can pretend it has them, but when you talk about "edge cases not working", they aren't going to work in spades here.
That doesn't really matter though, we're talking about practical bindings to C++ libraries here. It's a practical notion; it's natural to want to distribute the symbols among D modules that logically relate to the structure/layout of the C/C++ .h files. Or even adapt it slightly to fit among D modules more naturally to the D user. It's not a reasonable binding solution to tell the user they import one uber-module with the entire C++ lib. That's the only case where extern(C++, "ns") separating symbols by namespace is actually meaningful. If they're spread among respective D modules, as they would be, the name collision naturally won't happen, and it's very convenient to resolve if it does occur.
 This!!! You're on to it!!
 That's exactly what I want; I ***REALLLY*** want the compiler to emit
 that error message in that exact situation!
 Please, please can we have that? :)
No. If D is to support C++ namespaces, it has to support declaring the same identifier for different purposes in different namespaces. C++ namespaces have different scopes in C++. Doing anything else would make it impossible to connect to perfectly legitimate C++ programs. The WHOLE POINT of C++ namespaces is to support declaring the same identifier in different namespaces.
The point of supporting C++ namespaces is for mangling, and nothing more. We just want the linker to link. D already has a module system, it's excellent, and we want to use it exactly how it is. Its soul purpose is to allow you to declare the same identifier multiple times under different module namespaces. I don't want to see any change to D's standard naming patterns (as seen by the D library consumer) because the linker is linking to something that was compiled from C++. It should have no impact on D's normal naming/scoping rules. If the declaration is in the D module x.y, then the identifier is x.y.Identifier, just like EVERYTHING. If I didn't want it to be there, I would put it somewhere else. If I wanted it under x.y.ns.Identifier, I would make a module x.y.ns and put it there. If I have C++ ns1::X and ns2::X, then I can make respective D modules x.y.ns1 and x.y.ns2 and put each declaration of X in each one... normal D name resolution applies. I really don't understand what the problem is? There must be something I'm completely missing, because it makes no sense to me to make it impossible for the user to place the declaration where they want it, with no opt-out. There's nothing problematic or inconvenient about separating symbols with the same names into separate modules, that's what you do in D. We're not writing C++ code, we're writing a D api for use by normal D code. We're only *linking* to a C++ binary, and that's irrelevant to the user of the lib. They don't want to see weird C++ details creeping into the API, it would make no sense to the consumer. It should look like any normal D api to them.
 This would solve a lot of awkward issues.
It'd be a river of bug reports, because sure as shootin', people are going to try to interface to this C++ code: namespace ns1 { int identifier; } namespace ns2 { int identifier; } And why shouldn't they? It's correct and legitimate C++ code.
Sure, and they would have almost certainly made a module 'ns1' and another module 'ns2', and put each 'identifier' in their respective place. That's the natural thing to do as a D programmer, and if someone complains as you say, suggest they make another module for the other symbol... I don't believe the situation you propose will emerge; it would be unnatural for a D user to expect that 2 symbols with the same name would coexist in one module, and if it does, the solution is extremely simple, and works well... just as well as all other normal D code. Surely a D consumer of a C++ library would assume that the different C++ namespaces have been sensibly mapped to D modules appropriately by the person who wrote the bindings? The bindings will have been written and organised to present comfortably to a D user.
 Oh yeah, I just remembered another great case, I had this in C++:
    namespace delegate {}
 'delegate' is not a valid identifier in D, I was going to come in here
 and bang the drum again, and also suggest that the namespace needs to
 be a string, ie extern(C++, "delegate")
 D takes a lot more names from the namespace than C++ does.

 The user has _no control_ over what they name the C++ namespace; by
 definition, it already exists. It's for binding purposes. It might not
 even be a name that's a valid D identifier.
 It's just for mangling.
Please file an enhancement request for that. Though you can probably make it work by writing a C++ wrapper for it.
That would imply that binding to C++ libs may involve writing D bindings, and also additional C++ bindings/adapters. A developer will now need a parallel C++ build system to compile the adapter along with their project. We should make every effort to prevent that necessity as best we can, and I don't think making the namespace a string offers any disadvantage, but it reduces the chances of this sort of problem. I'll log an enhancement request. https://issues.dlang.org/show_bug.cgi?id=15512
 One involves more complex inheritence; we have typical C++
 'interfaces', ie, classes populated only with abstract virtuals, and
 multiple inheritence of those. Does extern(C++) currently support
 inheriting multiple interfaces?
Only if they have no fields, i.e. they mirror COM inheritance.
Yes, this is the case. Do you suspect this will work already? Situation is like this: class Base // normal C++ base class, has members { int members; virtual void baseVirtual(); }; class Interface // pure COM style interface class, no members { virtual void interfaceVirtual() = 0; }; class MultipleDerived : public Base, public Interface { int moreMembers; void baseVirtual() override {} // implement function from base void interfaceVirtual() override {} // also from interface }; This is the situation we have of some classes that need representation in D. Also, D code will further derive from MultipleDerived. Ie, in D: extern(C++) class Base { int members; /+virtual+/ void baseVirtual(); } extern(C++) interface Interface { void interfaceVirtual(); } extern(C++) class MultipleDerived : Base, Interface { int moreMembers; override void baseVirtual() {} // implement function from base override void interfaceVirtual() {} // also from interface } class DClass : MultipleDerived // D class derives from C++ base class { // D stuff } This all seems reasonable, the only bit I haven't tried yet is inheriting from a proper base class and also an interface. Will the extern(C++) class get this more complicated vtable structure right?
 I also expect I'll need a way to express a class instance. I noticed that
 in:

 extern(C++)
 {
    class C {}
    struct S(T) {}
 }
 S!C x;

 I noticed in one case like this that 'x' seemed to mangle as C++
 S<C*>, where the '*' in the mangled name seems to be implicit in D
 (presumably because D's classes are always references?).
 If that is indeed the case, we'll need a way to express a symbol name
 that is just the instance 'C', not 'C*'. But these will be advanced
 problems, with possible work-arounds when basic problems are solved.
D doesn't support "Shimmer" aggregates ("Is it a floor wax or a dessert topping?") You may need to write C++ wrappers for the problematic C++ types, and then interface to the wrappers.
You did magic mangling for c_long... it's going to be a big ongoing problem if we can't express a template symbol with a C without a '*' after it. C in the template signature is the common case, people almost always template on C, and add the * or & at the site of the C member declaration. Are you sure we can't invent some little marker template to inform the C++ mangler to leave off the '*'? Thing!(NoStar!Class) -> Thing<Class> An example, there is a C++ class like this: template<typename C> struct Thing { C *instance; // overwhelmingly common case; * (or &) on the member, rarely in the template static void f(); }; In D, this struct is defined to match as we expect: extern(C++) struct Thing(C) { C instance; // obviously, * is implicit in D, no problem static void f(); } Consider the C++ call: Thing<MyClass>::f();
From D, it would be: Thing!MyClass.f();
The structs are identical, the function is correct and compatible, this should work. Problem is, the C symbol is: Thing<MyClass>::f The extern(C++) symbol that D generates is: Thing<MyClass*>::f And you fail to link. If we could call: Thing!(NoStar!MyClass).f(); Where 'NoStar!' is just some thin skin, that could be a magic helper, like c_long, which makes this connection work.
Jan 04
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2016-01-03 06:40, Walter Bright wrote:

 I do not understand what difficulty you are having with this.
I think what Manu is finding difficult is that "extern(C++, ns)" creates a symbol at the D side. Which is kind of unexpected as no other for of "extern" works like that. That also makes it impossible to use the same namespace in different file, which is very common in C++. I think that code like: int x; extern (C++, ns) { char x; } Is less common than the using the same namespace in different files. It's also not very practical to create bindings for a complete library in a single module, if the library is big. -- /Jacob Carlborg
Jan 03
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/3/2016 7:02 AM, Jacob Carlborg wrote:
 On 2016-01-03 06:40, Walter Bright wrote:

 I do not understand what difficulty you are having with this.
I think what Manu is finding difficult is that "extern(C++, ns)" creates a symbol at the D side. Which is kind of unexpected as no other for of "extern" works like that.
I originally implemented the feature as 'namespace ns'. But nobody liked that, as it would encourage people to use namespaces for non-C++ interfacing purposes.
 That also makes it impossible to use the same namespace in
 different file, which is very common in C++.
It is not at all impossible, any more than it is impossible to declare C names in multiple files. But you do have to follow C/C++'s "One Definition Rule" or you'll get link errors.
 I think that code like:

 int x;
 extern (C++, ns) { char x; }

 Is less common than the using the same namespace in different files. It's also
 not very practical to create bindings for a complete library in a single
module,
 if the library is big.
I agree it is not very practical to put it all in one file. But it isn't any more necessary than putting all the C declarations in one file, for the same reason.
Jan 03
parent Jacob Carlborg <doob me.com> writes:
On 2016-01-03 16:59, Walter Bright wrote:

 It is not at all impossible, any more than it is impossible to declare C
 names in multiple files. But you do have to follow C/C++'s "One
 Definition Rule" or you'll get link errors.
Aha, I thought that was the problems that Manu had, my bad. At least it works for the simple cases.
 I agree it is not very practical to put it all in one file. But it isn't
 any more necessary than putting all the C declarations in one file, for
 the same reason.
My fault, see above. -- /Jacob Carlborg
Jan 03
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
Found and fixed another fwd ref problem with circular imports:

   https://github.com/D-Programming-Language/dmd/pull/5333

This one had nothing to do with C++ namespaces; it showed up for structs and 
classes, too. This implies that the current design is sound, and a redesign is 
not necessarily desirable.
Jan 06
parent reply Marc =?UTF-8?B?U2Now7x0eg==?= <schuetzm gmx.net> writes:
On Wednesday, 6 January 2016 at 17:55:01 UTC, Walter Bright wrote:
 Found and fixed another fwd ref problem with circular imports:

   https://github.com/D-Programming-Language/dmd/pull/5333

 This one had nothing to do with C++ namespaces; it showed up 
 for structs and classes, too. This implies that the current 
 design is sound, and a redesign is not necessarily desirable.
By reading Manu's post, I was under the impression that it was actually impossible to use the C++ symbol _without_ the full namespace path, like with static imports. I should have checked this, because it turns out this isn't true at all. I agree then that the current design is mostly ok, especially with your bug fixes. But there remains the issue of using D keywords in C++ namespaces. Maybe there could be a variant `extern(C++, "ns1.ns2.as.string")`, that doesn't create symbols and affects mangling only?
Jan 07
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2016-01-07 15:03, Marc Schütz wrote:

 But there remains the issue of using D keywords in C++ namespaces. Maybe
 there could be a variant `extern(C++, "ns1.ns2.as.string")`, that
 doesn't create symbols and affects mangling only?
It looks like extern(C++, ns) creates a symbol in the D code. If that's the case, then it should be possible, in theory, to attach pragma(mangle) to that symbol. pragma(mangle, "try") extern(C++, try_) { void foo(); } -- /Jacob Carlborg
Jan 07
parent Carl Sturtivant <sturtivant gmail.com> writes:
On Thursday, 7 January 2016 at 14:15:03 UTC, Jacob Carlborg wrote:
 On 2016-01-07 15:03, Marc Schütz wrote:

 But there remains the issue of using D keywords in C++ 
 namespaces. Maybe
 there could be a variant `extern(C++, "ns1.ns2.as.string")`, 
 that
 doesn't create symbols and affects mangling only?
It looks like extern(C++, ns) creates a symbol in the D code. If that's the case, then it should be possible, in theory, to attach pragma(mangle) to that symbol. pragma(mangle, "try") extern(C++, try_) { void foo(); }
Exactly: makes perfect sense, and deals with the problem uniformly as with other languages.
Jan 07
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/7/2016 6:03 AM, Marc Schütz wrote:
 But there remains the issue of using D keywords in C++ namespaces. Maybe there
 could be a variant `extern(C++, "ns1.ns2.as.string")`, that doesn't create
 symbols and affects mangling only?
I agree we need to do something about that. It doesn't just happen with namespaces names, it happens with all C++ symbols. We need a simple and more general solution. One possibility is to add a leading _ to such names: extern (C++, _delegate) The leading _ means 'strip the leading _ when mangling for C++'. If you need a leading _ in the C++ name, use two __ in the D name. And so on. This may break existing code. Perhaps the _ stripping can only happen when the stripped identifier is not a D keyword, that won't break anything. I know it's hackish, but it's awfully simple and straightforward. An analogous scheme is used in Ddoc, so there's precedent.
Jan 07
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2016-01-07 15:41, Walter Bright wrote:

 I agree we need to do something about that. It doesn't just happen with
 namespaces names, it happens with all C++ symbols. We need a simple and
 more general solution.
I think that for a symbol outside of the a namespace pragma(mangle) is enough. It's not _that_ many names that are reserved in D. What I do is I declare a symbol with a valid D identifier of the same length at the name I actually want. Then I print the mangled name using .mangleof. Alternatively enhance core.demangle.mangle to handle different linkages and namespaces. Although then ones needs to duplicate the signature.
 One possibility is to add a leading _ to such names:

      extern (C++, _delegate)
For namespaces it's a bit more problematic. But it looks like extern(C++, ns) creates a symbol in the D code. If that's the case, then it should be possible, in theory, to attach pragma(mangle) to that symbol. pragma(mangle, "delegate") extern(C++, delegate_) { void foo(); } -- /Jacob Carlborg
Jan 07
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 01/07/2016 10:51 AM, Jacob Carlborg wrote:
 pragma(mangle, "delegate") extern(C++, delegate_)
 {
      void foo();
 }
I think we're fine with asking people to define renaming shims on the C++ side for the initial release. -- Andrei
Jan 07
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/7/2016 7:51 AM, Jacob Carlborg wrote:
 But it looks like extern(C++, ns)
 creates a symbol in the D code. If that's the case,
I can clear this up - that's exactly what it does!
Jan 07
parent reply Jacob Carlborg <doob me.com> writes:
On 2016-01-07 17:55, Walter Bright wrote:

 I can clear this up - that's exactly what it does!
So is the compiler treating the namespace symbol differently? Or isn't it possible to attached pragma(mangle) to a struct? -- /Jacob Carlborg
Jan 07
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/7/2016 11:56 PM, Jacob Carlborg wrote:
 On 2016-01-07 17:55, Walter Bright wrote:

 I can clear this up - that's exactly what it does!
So is the compiler treating the namespace symbol differently?
?? differently than what?
 Or isn't it possible to attached pragma(mangle) to a struct?
Yes, it is. But structs have other semantics that are not the same as namespaces.
Jan 08
parent reply Jacob Carlborg <doob me.com> writes:
On 2016-01-08 14:36, Walter Bright wrote:

 ?? differently than what?
Than a struct, for example. -- /Jacob Carlborg
Jan 08
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/8/2016 5:59 AM, Jacob Carlborg wrote:
 On 2016-01-08 14:36, Walter Bright wrote:

 ?? differently than what?
Than a struct, for example.
Symbol lookups work the same. Semantics are different. For example, namespaces do not have default copy constructors, and do not have instances.
Jan 08
parent Jacob Carlborg <doob me.com> writes:
On 2016-01-08 15:05, Walter Bright wrote:

 Symbol lookups work the same. Semantics are different. For example,
 namespaces do not have default copy constructors, and do not have
 instances.
Of course the semantics are not the same, otherwise they would be the same thing ;). It was more thinking of what pragma(mangle) can be attached to how the mangling works. -- /Jacob Carlborg
Jan 08
prev sibling parent Carl Sturtivant <sturtivant gmail.com> writes:
On Thursday, 7 January 2016 at 14:41:41 UTC, Walter Bright wrote:
 On 1/7/2016 6:03 AM, Marc Schütz wrote:
 But there remains the issue of using D keywords in C++ 
 namespaces. Maybe there
 could be a variant `extern(C++, "ns1.ns2.as.string")`, that 
 doesn't create
 symbols and affects mangling only?
I agree we need to do something about that. It doesn't just happen with namespaces names, it happens with all C++ symbols. We need a simple and more general solution. One possibility is to add a leading _ to such names: extern (C++, _delegate) The leading _ means 'strip the leading _ when mangling for C++'. If you need a leading _ in the C++ name, use two __ in the D name. And so on. This may break existing code. Perhaps the _ stripping can only happen when the stripped identifier is not a D keyword, that won't break anything. I know it's hackish, but it's awfully simple and straightforward. An analogous scheme is used in Ddoc, so there's precedent.
Right now pragma(mangle...) doesn't work with C++ functions in namespaces! Surely this is something desirable in its own right. Is there some reason that pragma(mangle,...) cannot be made to apply to C++ functions in namespaces? This is clearly the right answer. And it doesn't presume to know what the mangling is being used for. Which is to say it follows the D philosophy of providing options for how solutions are constructed without imposing upon the author, rather than acting in a "we know best" fashion, presuming to know all the possibilities for use.
Jan 07
prev sibling parent reply Carl Sturtivant <sturtivant gmail.com> writes:
On Thursday, 7 January 2016 at 14:03:25 UTC, Marc Schütz wrote:
 On Wednesday, 6 January 2016 at 17:55:01 UTC, Walter Bright 
 wrote:
 Found and fixed another fwd ref problem with circular imports:

   https://github.com/D-Programming-Language/dmd/pull/5333

 This one had nothing to do with C++ namespaces; it showed up 
 for structs and classes, too. This implies that the current 
 design is sound, and a redesign is not necessarily desirable.
By reading Manu's post, I was under the impression that it was actually impossible to use the C++ symbol _without_ the full namespace path, like with static imports. I should have checked this, because it turns out this isn't true at all. I agree then that the current design is mostly ok, especially with your bug fixes.
I should have noticed this too; so in fact the current design can be used ignoring the scope modeling the C++ namespace. If the details of using such an external name in that fashion are identical to any other name at module scope in every context, then I therefore concede that the design is OK, because it may be treated as the alternative suggested in various ways in this thread by simply ignoring the new scope by not using its name.
Jan 07
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/7/2016 9:02 AM, Carl Sturtivant wrote:
 I should have noticed this too; so in fact the current design can be used
 ignoring the scope modeling the C++ namespace. If the details of using such an
 external name in that fashion are identical to any other name at module scope
in
 every context, then I therefore concede that the design is OK, because it may
be
 treated as the alternative suggested in various ways in this thread by simply
 ignoring the new scope by not using its name.
The idea is most definitely that it follows the usual D scoping and name lookup rules. Note that 'alias' works much like symbolic links do in the Linux filesystem, in that it can make names appear in multiple scopes without needing qualification.
Jan 07
parent reply Carl Sturtivant <sturtivant gmail.com> writes:
On Thursday, 7 January 2016 at 18:17:24 UTC, Walter Bright wrote:
 On 1/7/2016 9:02 AM, Carl Sturtivant wrote:
 I should have noticed this too; so in fact the current design 
 can be used
 ignoring the scope modeling the C++ namespace. If the details 
 of using such an
 external name in that fashion are identical to any other name 
 at module scope in
 every context, then I therefore concede that the design is OK, 
 because it may be
 treated as the alternative suggested in various ways in this 
 thread by simply
 ignoring the new scope by not using its name.
The idea is most definitely that it follows the usual D scoping and name lookup rules. Note that 'alias' works much like symbolic links do in the Linux filesystem, in that it can make names appear in multiple scopes without needing qualification.
So what do you make of Manu's last post? http://forum.dlang.org/post/mailman.3421.1452230079.22025.digitalmars-d puremagic.com Specifically, he gives examples of name collisions and scope problems that apparently could be avoided simply only if there is no named scope modeling a C++ namespace.
Jan 30
parent Carl Sturtivant <sturtivant gmail.com> writes:
On Saturday, 30 January 2016 at 21:06:22 UTC, Carl Sturtivant 
wrote:

 So what do you make of Manu's last post?
 http://forum.dlang.org/post/mailman.3421.1452230079.22025.digitalmars-d puremagic.com

 Specifically, he gives examples of name collisions and scope 
 problems that apparently could be avoided simply only if there 
 is no named scope modeling a C++ namespace.
Apologies, I somehow posted while unaware of all the intervening discussion.
Jan 30
prev sibling parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 8 January 2016 at 03:02, Carl Sturtivant via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Thursday, 7 January 2016 at 14:03:25 UTC, Marc Schütz wrote:
 On Wednesday, 6 January 2016 at 17:55:01 UTC, Walter Bright wrote:
 Found and fixed another fwd ref problem with circular imports:

   https://github.com/D-Programming-Language/dmd/pull/5333

 This one had nothing to do with C++ namespaces; it showed up for structs
 and classes, too. This implies that the current design is sound, and a
 redesign is not necessarily desirable.
By reading Manu's post, I was under the impression that it was actually impossible to use the C++ symbol _without_ the full namespace path, like with static imports. I should have checked this, because it turns out this isn't true at all. I agree then that the current design is mostly ok, especially with your bug fixes.
I should have noticed this too; so in fact the current design can be used ignoring the scope modeling the C++ namespace. If the details of using such an external name in that fashion are identical to any other name at module scope in every context, then I therefore concede that the design is OK, because it may be treated as the alternative suggested in various ways in this thread by simply ignoring the new scope by not using its name.
Again, this is looking at the simple case. The details and more complex scenarios start to reveal problems. If the same C++ namespace is present in multiple modules, that is, x.ns and y.ns, you want to 'import x, y;', the symbols from x and y are imported into the local module scope, but now you have a name conflict on 'ns'. Does the imported 'ns' refer to x.ns or y.ns? This case is everywhere, since every module with extern(C++, ns) will have the same top-level symbol. We considered a case where you do import renaming, for instance: import x : newname = symbol; This no longer works, we would need a further 'enhancement' such that: import x : newnane = ns.symbol; is a valid statement. I had another case where a mixin template would refer to some symbol, the name resolution breaks down when multiple imports define the same C++ namespace (which they basically all do), and it gave errors that it was unable to find the function I was referring to, despite the module that defines it being imported at top-level. My point remains, the namespace scope introduces a lot of complexity, we're likely going to have to add further 'features' to make it not broken and work in all the edge cases, and there's still no good reason for it to exist at all... how is it that removing a point of complexity and thus solving a bunch of related problems could not be better than adding further complexity to try and round off something that is already a point of needless complexity? The module system works, it's completely reliable. We want to use it exactly how it is. Walter: if you insist that namespace scopes MUST exist for reasons that make no sense to me no matter how I look at it, then give us an opt out. It should not require more complex code to undo complexity and represent something that is, in fact, less complex, ie: extern(C++, ns) struct Thing {} alias Thing = ns.Thing; That is needless complexity, it affects _every single extern(C++) declaration_ in my program, and I only know to do that because I am an expert... why would anyone else on my team, a junior for instance, know to do that? It's just asking for trouble. If I forget that alias, the errors can be rather unintuitive. They will interrupt me, and I would have to explain it. The namespace offers nothing, and introduces problems. We don't want it.
Jan 07
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2016-01-08 06:14, Manu via Digitalmars-d wrote:

 Again, this is looking at the simple case. The details and more
 complex scenarios start to reveal problems.

 If the same C++ namespace is present in multiple modules, that is,
 x.ns and y.ns, you want to 'import x, y;', the symbols from x and y
 are imported into the local module scope, but now you have a name
 conflict on 'ns'. Does the imported 'ns' refer to x.ns or y.ns? This
 case is everywhere, since every module with extern(C++, ns) will have
 the same top-level symbol.
This is what I have found out: module foo; extern(C++, ns) { int a(); } module bar; extern(C++, ns) { int b(); } module main; import foo; import bar; extern(C++, ns) { int c(); } void main() { a(); b(); c(); // ns.a(); // does not work foo.ns.a(); ns.c(); } "ns.a()" works if there is no other extern(C++, ns), either in "main" or "bar". Is that working for you, or do you have more complex examples where the above doesn't work? Walter, should "ns.a()" work in the above example? -- /Jacob Carlborg
Jan 08
next sibling parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 8 January 2016 at 18:11, Jacob Carlborg via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 void main()
 {
     a();
     b();
     c();
Eh? This has caused me many errors in the past, perhaps in slightly more complex situations though. Try all this, but with structs and classes and references from member functions to the other modules and all that good stuff. If only one 'ns' is present (surely import can only place one ns in the local scope?), how can it find its way through the others to find all these symbols?
     // ns.a(); // does not work
There are 3 different 'ns's, how could it disambiguate?
     foo.ns.a();
     ns.c();
I've noticed that the local ns 'wins'?
 }

 "ns.a()" works if there is no other extern(C++, ns), either in "main" or
 "bar". Is that working for you, or do you have more complex examples where
 the above doesn't work?
That's the problem with multiple definitions of the same ns, but I've also had problems referring to the inner symbols without the scope appended, which is all you really want to do (as you did at the top). Let me do some new tests with the latest DMD, since the forward referencing bugs were also plaguing me, I may have been hit by a lot of false-positive failures in my tests by that bug.
Jan 08
next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 1/8/2016 2:03 AM, Manu via Digitalmars-d wrote:
 There are 3 different 'ns's, how could it disambiguate?
Explained in my reply to Jacob. I can't agree with "it's all wrong" if it is not understood how it works. Maybe Ali's book explains it better, I have certainly failed at explaining it.
Jan 08
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2016-01-08 11:03, Manu via Digitalmars-d wrote:

 Let me do some new tests with the latest DMD, since the forward
 referencing bugs were also plaguing me, I may have been hit by a lot
 of false-positive failures in my tests by that bug.
My small example was with DMD 2.069.1. -- /Jacob Carlborg
Jan 08
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/8/2016 12:11 AM, Jacob Carlborg wrote:
 Walter, should "ns.a()" work in the above example?
No: 1. first "ns.a" looks up "ns". Finds it in the current module, "main.ns". 2. Looks "a" up in "main.ns". "a" is not there. Error. "a()" works because: 1. Look up "a" in current module. Doesn't find it. 2. Look up "a" in import "foo". 1. doesn't find it. Look in imported scope "foo.ns". finds it. 3. Look up "a" in import "bar". 1. doesn't find it. Look in imported scope "bar.ns". Doesn't find it. Found only one "a" in the imports. We have da winnah! I think name lookup rules are straightforward in D. I explain them over and over, for years, and nobody but me understands them. I find it very frustrating.
Jan 08
next sibling parent Jacob Carlborg <doob me.com> writes:
On 2016-01-08 14:50, Walter Bright wrote:

 No:

 1. first "ns.a" looks up "ns". Finds it in the current module, "main.ns".
 2. Looks "a" up in "main.ns". "a" is not there. Error.

 "a()" works because:

 1. Look up "a" in current module. Doesn't find it.
 2. Look up "a" in import "foo".
     1. doesn't find it. Look in imported scope "foo.ns". finds it.
 3. Look up "a" in import "bar".
     1. doesn't find it. Look in imported scope "bar.ns". Doesn't find it.

 Found only one "a" in the imports. We have da winnah!

 I think name lookup rules are straightforward in D. I explain them over
 and over, for years, and nobody but me understands them. I find it very
 frustrating.
Yeah, I know, you have explained it several times. Although it doesn't always feel intuitive when you're actually writing the code. It's not like the above rules are hard to understand, it's just that I don't think of the look up rules above when I'm actually writing code. -- /Jacob Carlborg
Jan 08
prev sibling next sibling parent Jason Jeffory <JasonJeffory doodle.com> writes:
On Friday, 8 January 2016 at 13:50:56 UTC, Walter Bright wrote:
 On 1/8/2016 12:11 AM, Jacob Carlborg wrote:
 Walter, should "ns.a()" work in the above example?
No: 1. first "ns.a" looks up "ns". Finds it in the current module, "main.ns". 2. Looks "a" up in "main.ns". "a" is not there. Error. "a()" works because: 1. Look up "a" in current module. Doesn't find it. 2. Look up "a" in import "foo". 1. doesn't find it. Look in imported scope "foo.ns". finds it. 3. Look up "a" in import "bar". 1. doesn't find it. Look in imported scope "bar.ns". Doesn't find it. Found only one "a" in the imports. We have da winnah! I think name lookup rules are straightforward in D. I explain them over and over, for years, and nobody but me understands them. I find it very frustrating.
Lol, that either tells you that you've got it wrong or that your just too smart! How bout this, add compiler functionality where one can contribute patches to dmd, and then experimentally use them? If Manu has such capabilities, he could check his "theory" about quite easily(his code would just work)... at leas then everyone would know what the real issue is. As much time that has been wasted arguing over this stuff, the feature and fix could have been implemented already. e.g., dmd ... -expermental-nsmodule .... Not that it matters, my own personal logic tells me that namespace resolution should be consistent with D module name resolution. To treat all namespaces sort of coming from a global chunk of symbols just seems wrong. The whole point in the first place was to get around that. Reverting back to C like scope resolution for something that was suppose to get away from it doesn't make sense logically. Basically there are two choices, D Namespaces are module bound(moduleA.ns2 is different than moduleB.ns2) or they are not(moduleA.ns2 is the same as moduleB.ns2). How bout this for a solution? Create a new namespace keyword, _namspace or inline namespace or whatever, it behaves one way and the other behaves the other way?? This way, everyone wins!!!! Who cares about people that "might abuse" something... that's trying to solve a problem that doesn't exist yet. If people want to shoot themselves in the foot, let them, they will learn, and like everything else, one will become deprecated over time, it's nothing new. It's like trying to prevent people from walking because someone once fell in a man-hole. 99.9% of people are good at walking. Punish them for the edge case? Maybe the issue is the man hole instead? I imagine it would be easier to write a utility that parses the C++ code and does some magic to make it work in D than getting D to support something that it already does differently.
Jan 10
prev sibling parent reply Rainer Schuetze <r.sagitario gmx.de> writes:
On 08.01.2016 14:50, Walter Bright wrote:
 On 1/8/2016 12:11 AM, Jacob Carlborg wrote:
 Walter, should "ns.a()" work in the above example?
No: 1. first "ns.a" looks up "ns". Finds it in the current module, "main.ns". 2. Looks "a" up in "main.ns". "a" is not there. Error. "a()" works because: 1. Look up "a" in current module. Doesn't find it. 2. Look up "a" in import "foo". 1. doesn't find it. Look in imported scope "foo.ns". finds it. 3. Look up "a" in import "bar". 1. doesn't find it. Look in imported scope "bar.ns". Doesn't find it. Found only one "a" in the imports. We have da winnah! I think name lookup rules are straightforward in D. I explain them over and over, for years, and nobody but me understands them. I find it very frustrating.
Just to clarify: namespaces don't apply "normal" symbol lookup rules (as inside structs), but create a "named scope" according to the docs (a term never used elsewhere). That means it behaves like a template mixin with lookup rules very similar to imports. Walter, maybe you can show how STL is supposed to be wrapped and used. I tried this (using stl as package to avoid conflicts with std): ////////////////////////////// module stl.map; extern(C++,std) struct map(K,V) { V[K] data; } ////////////////////////////// module stl.vector; extern(C++,std) struct vector(T) { T[] data; } ////////////////////////////// import stl.vector; import stl.map; //import std.stdio; //import std.algorithm; void main() { std.vector!int v; std.map!(int,int) m; // writeln(v); } This yields: test.d(11): Error: stl.vector.std at stl\vector.d(3) conflicts with stl.map.std at stl\map.d(3) test.d(12): Error: stl.vector.std at stl\vector.d(3) conflicts with stl.map.std at stl\map.d(3) test.d(12): Error: template identifier 'map' is not a member of namespace 'stl.vector.std' It gets worse if you add D's std package into the mix by adding the commented lines: test.d(11): Error: template identifier 'vector' is not a member of import 'test.std' test.d(12): Error: template identifier 'map' is not a member of import 'test.std' This works to disambiguate, but it is not nice (but maybe inevitable): void main() { stl.vector.vector!int v; stl.map.map!(int,int) m; writeln(v); }
Jan 11
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/11/2016 12:45 AM, Rainer Schuetze wrote:
 This yields:

 test.d(11): Error: stl.vector.std at stl\vector.d(3) conflicts with stl.map.std
 at stl\map.d(3)
 test.d(12): Error: stl.vector.std at stl\vector.d(3) conflicts with stl.map.std
 at stl\map.d(3)
 test.d(12): Error: template identifier 'map' is not a member of namespace
 'stl.vector.std'
Of course it does, because you're looking up "std" and "std" is in both vector and map. Again, I am hornswoggled by my inability to explain how name lookup works.
 This works to disambiguate, but it is not nice (but maybe inevitable):

 void main()
 {
      stl.vector.vector!int v;
      stl.map.map!(int,int) m;

      writeln(v);
 }
Following the rules I listed: import stl.vector; import stl.map; void main() { vector!int v; map!(int,int) m; } compiles without error.
Jan 11
parent reply Rainer Schuetze <r.sagitario gmx.de> writes:
On 11.01.2016 18:40, Walter Bright wrote:
 On 1/11/2016 12:45 AM, Rainer Schuetze wrote:
 This yields:

 test.d(11): Error: stl.vector.std at stl\vector.d(3) conflicts with
 stl.map.std
 at stl\map.d(3)
 test.d(12): Error: stl.vector.std at stl\vector.d(3) conflicts with
 stl.map.std
 at stl\map.d(3)
 test.d(12): Error: template identifier 'map' is not a member of namespace
 'stl.vector.std'
Of course it does, because you're looking up "std" and "std" is in both vector and map. Again, I am hornswoggled by my inability to explain how name lookup works.
No need to explain. I'm just showing that the name lookup that might be expected from a C++ namespace, doesn't work. I suspect that's Manus' argument: if it gets unusable so easily then why add it it in the first place? As the usual disambiguation techniques work I'm not sure the additional symbol does any harm, though.
Jan 11
next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 1/11/2016 10:58 AM, Rainer Schuetze wrote:
 No need to explain. I'm just showing that the name lookup that might be
expected
 from a C++ namespace, doesn't work. I suspect that's Manus' argument: if it
gets
 unusable so easily then why add it it in the first place?
I suspect that people are thinking that "std.map" is being looked up. That is not the case. "std" is looked up, and if that is successful on its own, then "map" is looked up. Looking up "std.map" occurs nowhere in D or C++, why do people impute this behavior?
 As the usual disambiguation techniques work I'm not sure the additional symbol
 does any harm, though.
Hence my wondering what the actual problem Manu is having is.
Jan 11
prev sibling parent reply Daniel N <ufo orbiting.us> writes:
On Monday, 11 January 2016 at 18:58:42 UTC, Rainer Schuetze wrote:
 As the usual disambiguation techniques work I'm not sure the 
 additional symbol does any harm, though.
No real harm, but it pollutes, that's my main gripe with it anyway. I'd rather not see any stuttering symbols. 1) Editor auto-completion annoyance. 2) Debug info annoyance. 3) Reflection annoyance. Well, at least with my private-symbol workaround I can diminish the issue.
Jan 11
parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 12 January 2016 at 08:03, Daniel N via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 3) Reflection annoyance.
Oh god, I didn't think of that! But I'll definitely run into it soon enough. How annoying >_< Existing reflection systems will fail in this case, which would have otherwise worked just fine without modification.
 Well, at least with my private-symbol workaround I can diminish the issue.
Surely the fact that people are implementing machinery to undo the damage done is a strong indication that they don't want the feature. Please, can anyone produce an argument in favour...? Otherwise just accept that it was a bad idea and eject it into space. Why could anyone be attached to it?
Jan 11
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/11/2016 8:02 PM, Manu via Digitalmars-d wrote:
 Surely the fact that people are implementing machinery to undo the
 damage done is a strong indication that they don't want the feature.
 Please, can anyone produce an argument in favour...? Otherwise just
 accept that it was a bad idea and eject it into space.
 Why could anyone be attached to it?
I already did for your scheme: int a; extern (C++,ns) { int a; } // error! The whole point of namespaces in C++ is to introduce scoped names. Not putting them in a scope might work for your project, but in general it will not, and the workarounds you suggested for it (putting them in separate modules) are awkward. All (*) the specific examples you've posted about fundamental problems with the current scheme have been adequately addressed (bugs were fixed, and misunderstandings clarified). Nobody in this thread has been able to determine, with an example, what all the other problems you talk about are. (*) except the delegate one, and there are a couple solutions on the table for that. I want to deal with the problems you're having, and find a solution. But without examples illustrating them, I am dead in the water and cannot help.
Jan 12
parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 13 January 2016 at 03:20, Walter Bright via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 1/11/2016 8:02 PM, Manu via Digitalmars-d wrote:
 Surely the fact that people are implementing machinery to undo the
 damage done is a strong indication that they don't want the feature.
 Please, can anyone produce an argument in favour...? Otherwise just
 accept that it was a bad idea and eject it into space.
 Why could anyone be attached to it?
I already did for your scheme: int a; extern (C++,ns) { int a; } // error!
Of course that's an error, declaring 2 symbols with the same name at the top level of the same module is obviously an error. No D coder would expect otherwise. There's no realistic scenario that could lead to that case; why would you have an extern(C++) symbol in some module and also want to put a D symbol with the same name in the same place? The only case I can imagine is you might want an extern(D) overload which wraps an extern(C++) function, but that works fine so there's no issue there.
 The whole point of namespaces in C++ is to introduce scoped names.
But we already have scoped names in D, so implementing that semantic for that reason has no value in D. We just want to link to C++ code. We don't want C++ concepts invading D, especially when the problem is already solved. We have a well defined module system. There's no reason, and no desire to deviate from that in any way whatsoever. I suggest that, if you're convinced namespaces must exist to address the non-issue you present above, then it should be a separate opt-in feature. As far as I know, we're yet to hear from someone who wants that behaviour by default.
 Not putting them in a scope might work for your project, but in general it will
 not, and the workarounds you suggested for it (putting them in separate
 modules) are awkward.
This seems to be the foundation of our disagreement. I can't understand how you can make this claim, please demonstrate how using modules is awkward? It's not awkward to put your code in a module, it's normal... infact, it's impossible to put D code anywhere other than in a module. All D code is in a module... so, how can that possibly be considered awkward or inconvenient? Organising modules *IS* coding in D, and a user of extern(C++) wouldn't expect that they are suddenly following a different set of patterns or rules. They will continue to organise their code in modules however they usually do, in whatever way best suits their project or API.
 All (*) the specific examples you've posted about fundamental problems with
 the current scheme have been adequately addressed (bugs were fixed, and
 misunderstandings clarified). Nobody in this thread has been able to
 determine, with an example, what all the other problems you talk about are.
Sure, bugs have been fixed, and I'm certain we can further make this 'work' as the design intends, but that has come at great cost in time and energy so far; a cost which never needed to be spent, and further effort is required. But the point is, making this work as designed doesn't necessarily put us in a state we're happy with. Rainer presented a case for confusion; you're making an argument that the scope is to make it feel kinda like C++ code, but it doesn't really behave like C++ at all. You can re-open namespaces and add symbols into existing namespaces until the cows come home in C++, but in D you end out with multiple definitions of the same named namespaces in different modules, and then you need to use the full name (including the module) to disambiguate... which surely makes plain the reality of the situation, which is that the namespace **is the module**, not the C++ namespace. Requiring the full module name to disambiguate leaves the namespace redundant. I have never, not ever, seen a C++ program where the same namespace isn't used in basically every source file. After mapping those source files to D modules, you will have the same namespace defined in every module, at which point the namespace only acts against it's stated worth. Further, the namespace almost certainly collides with D's top level package name. Other problems like Daniel presented regarding reflection are just annoying work which doesn't need to happen. Reflection of the kind that scans scopes for symbols requires new logic which recurses into C++ namespaces, and no existing reflection code will have support for that. (Do we actually have __traits which can do that currently? Can we detect if symbol is a C++ namespace?) One workaround for that is to alias the symbols from the namespace into the outer scope, which is just a bunch of pointless work and noise in the code, but we then want to make the namespace itself private such that the aliases become the API. Since alias is unable to make private symbols visible by aliasing them into a public scope, that leads to effort to create awkward kludges like Daniel presented to hide the namespace, or the approach I used which involves static import of cascading modules, and putting all the aliases in the outer module, doubling the number of files and obscuring the code tree.
 I want to deal with the problems you're having, and find a solution. But
 without examples illustrating them, I am dead in the water and cannot help.
I understand, and I've said I'll find the time to reduce my case and we can do that work. I just don't have any free time at work right now, I'll get to this as soon as I can. Regarding this discussion, as far as I'm concerned, this is a separate conversation regarding the validity of the features existence. I want to convince you that it's wrong. Fixing the existing design is a separate conversation, which I'll reopen as soon as I have more information for you. Of course, it would save a lot of effort if you agreed that the design is wrong, and none of us need to do anything further.
Jan 12
next sibling parent Jason Jeffory <JasonJeffory doodle.com> writes:
New construct to solve the problem!

extern(C++, nsin, nsout)

The nsin is the C++ namespace to import from and nsout is the D 
namespace that the symbol ends up being in. You can default nsout 
to be local, global, or whatever one wants.
Jan 12
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/12/2016 8:46 PM, Manu via Digitalmars-d wrote:
 Of course that's an error, declaring 2 symbols with the same name at
 the top level of the same module is obviously an error. No D coder
 would expect otherwise.
 There's no realistic scenario that could lead to that case; why would
 you have an extern(C++) symbol in some module and also want to put a D
 symbol with the same name in the same place?
If you like: extern (C++) { int a; extern (C++,ns) { int a; } } The whole point of scoped names is to be able to do this. Also, I would expect to be able to access "ns.a" with the syntax "ns.a", meaning ns has to be a scope.
 Of course, it would save a lot of effort if you agreed that the design
is wrong, and none of us need to do anything further. I regard it as crucial to determine the cause of your problems before assuming it is the design.
Jan 12
next sibling parent reply =?UTF-8?Q?Martin_Dra=c5=a1ar?= via Digitalmars-d writes:
Dne 13.1.2016 v 7:51 Walter Bright via Digitalmars-d napsal(a):
 If you like:
 
     extern (C++) {
         int a;
         extern (C++,ns) {
             int a;
         }
     }
 
 The whole point of scoped names is to be able to do this.
 
 Also, I would expect to be able to access "ns.a" with the syntax "ns.a",
 meaning ns has to be a scope.
The question is, how often would you want to do that in a real-world scenarios? By catering for this particular use-case, things got needlessly more complicated. It is quite strange that you consider using D's module system as awkward, yet you have no problem with all the convoluted solutions to Manu's problem. The scoping introduces only a poor man's analogy to C++ namespaces. As was pointed out by others, the same namespace tends to reside in many C++ files and if you attempt to mimic that file structure in D, you will have to disambiguate. Which leaves you with a weird combination of module system and namespaces. Your solution with Rainer's example on map and vector is to _not_ use the namespace at all, which is in conflict with your statement that you 'would expect to be able to access "ns.a" with the syntax "ns.a"'.
 Of course, it would save a lot of effort if you agreed that the design
is wrong, and none of us need to do anything further. I regard it as crucial to determine the cause of your problems before assuming it is the design.
I am with Manu on this one. Introducing scoping to C++ namespaces is a design mistake, because it fails to deliver on its promise to emulate true C++ namespaces. Namespaces in extern declaration should only affect linking and leave everything else to D's module system. Martin
Jan 13
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Wednesday, 13 January 2016 at 09:11:43 UTC, Martin Drašar 
wrote:
 I am with Manu on this one. Introducing scoping to C++ 
 namespaces is a design mistake, because it fails to deliver on 
 its promise to emulate true C++ namespaces.
Next version of C++ will probably allow this: namespace a::b::c::d::e { ... }
Jan 13
parent NX <nightmarex1337 hotmail.com> writes:
On Wednesday, 13 January 2016 at 10:53:06 UTC, Ola Fosheim 
Grøstad wrote:
 Next version of C++ will probably allow this:

 namespace a::b::c::d::e {
    ...
 }
Current version of D2 allow this: module a.b.c.d.e;
Jan 13
prev sibling next sibling parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 13 January 2016 at 16:51, Walter Bright via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 1/12/2016 8:46 PM, Manu via Digitalmars-d wrote:
 Of course, it would save a lot of effort if you agreed that the design
is wrong, and none of us need to do anything further. I regard it as crucial to determine the cause of your problems before assuming it is the design.
I managed to quickly reduce to this point again: module m.x; alias X2 = X; extern (C++, ns) struct X {} Error: undefined identifier 'X' I was using the nightly from the other night that I used to test the alias fix, but it seems to be the same thing. I figured I must be using the wrong toolchain somehow, purged DMD from my machine, confirmed the compiler was gone from path, got the nightly from last night: (https://builds.dawg.eu/dmd-2016-01-13/), tried it again, same error. Not sure... I tested this fix the other day, but now I'm seeing it again. That patch was merged right? Should be present in the nightly?
Jan 13
next sibling parent reply Meta <jared771 gmail.com> writes:
On Thursday, 14 January 2016 at 01:33:01 UTC, Manu wrote:
 I managed to quickly reduce to this point again:

 module m.x;
 alias X2 = X;
 extern (C++, ns) struct X {}

 Error: undefined identifier 'X'

 I was using the nightly from the other night that I used to 
 test the
 alias fix, but it seems to be the same thing.
 I figured I must be using the wrong toolchain somehow, purged 
 DMD from
 my machine, confirmed the compiler was gone from path, got the 
 nightly
 from last night: (https://builds.dawg.eu/dmd-2016-01-13/), 
 tried it
 again, same error.
 Not sure... I tested this fix the other day, but now I'm seeing 
 it
 again. That patch was merged right? Should be present in the 
 nightly?
Shouldn't that be `alias X2 = ns.X`?
Jan 13
parent Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 14 January 2016 at 11:52, Meta via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Thursday, 14 January 2016 at 01:33:01 UTC, Manu wrote:
 I managed to quickly reduce to this point again:

 module m.x;
 alias X2 = X;
 extern (C++, ns) struct X {}

 Error: undefined identifier 'X'

 I was using the nightly from the other night that I used to test the
 alias fix, but it seems to be the same thing.
 I figured I must be using the wrong toolchain somehow, purged DMD from
 my machine, confirmed the compiler was gone from path, got the nightly
 from last night: (https://builds.dawg.eu/dmd-2016-01-13/), tried it
 again, same error.
 Not sure... I tested this fix the other day, but now I'm seeing it
 again. That patch was merged right? Should be present in the nightly?
Shouldn't that be `alias X2 = ns.X`?
No, that's the whole point. If we need to do ns.X, then the whole thing becomes unusable as soon as you have 2 modules.
Jan 13
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/13/2016 5:33 PM, Manu via Digitalmars-d wrote:
 I managed to quickly reduce to this point again:

 module m.x;
 alias X2 = X;
 extern (C++, ns) struct X {}

 Error: undefined identifier 'X'
It's a bug. Thanks for finding and posting it. https://issues.dlang.org/show_bug.cgi?id=15565 As a workaround for the moment, you can either move the alias past the extern, or qualify X with ns.X.
Jan 13
next sibling parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 14 January 2016 at 15:39, Walter Bright via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 1/13/2016 5:33 PM, Manu via Digitalmars-d wrote:
 I managed to quickly reduce to this point again:

 module m.x;
 alias X2 = X;
 extern (C++, ns) struct X {}

 Error: undefined identifier 'X'
It's a bug. Thanks for finding and posting it. https://issues.dlang.org/show_bug.cgi?id=15565 As a workaround for the moment, you can either move the alias past the extern, or qualify X with ns.X.
Isn't this exactly what you fixed the other day? What's the difference between this and that prior forward referencing case?
Jan 14
parent Walter Bright <newshound2 digitalmars.com> writes:
On 1/14/2016 12:53 AM, Manu via Digitalmars-d wrote:
 Isn't this exactly what you fixed the other day? What's the difference
 between this and that prior forward referencing case?
The difference is that for this one, "X" is in "ns" and "ns" has not yet had its members added to the symbol table.
Jan 14
prev sibling next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 01/14/2016 12:39 AM, Walter Bright wrote:
 On 1/13/2016 5:33 PM, Manu via Digitalmars-d wrote:
 I managed to quickly reduce to this point again:

 module m.x;
 alias X2 = X;
 extern (C++, ns) struct X {}

 Error: undefined identifier 'X'
It's a bug. Thanks for finding and posting it. https://issues.dlang.org/show_bug.cgi?id=15565 As a workaround for the moment, you can either move the alias past the extern, or qualify X with ns.X.
Thanks Manu for reducing the bug!! -- Andrei
Jan 14
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/13/2016 9:39 PM, Walter Bright wrote:
    https://issues.dlang.org/show_bug.cgi?id=15565
https://issues.dlang.org/show_bug.cgi?id=15565
Jan 14
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/14/2016 6:24 PM, Walter Bright wrote:
 On 1/13/2016 9:39 PM, Walter Bright wrote:
    https://issues.dlang.org/show_bug.cgi?id=15565
https://issues.dlang.org/show_bug.cgi?id=15565
I meant: https://github.com/D-Programming-Language/dmd/pull/5351
Jan 14
next sibling parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 15 January 2016 at 12:25, Walter Bright via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 1/14/2016 6:24 PM, Walter Bright wrote:
 On 1/13/2016 9:39 PM, Walter Bright wrote:
    https://issues.dlang.org/show_bug.cgi?id=15565
https://issues.dlang.org/show_bug.cgi?id=15565
I meant: https://github.com/D-Programming-Language/dmd/pull/5351
Confirm that problem is solved in latest daily. Next one: void f() { j = 0; // works as expected k = 0; // fail } private: __gshared int j; extern(C++, ns) __gshared int k;
 Error: module x variable x.ns.k is private
Jan 17
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/17/2016 9:32 PM, Manu via Digitalmars-d wrote:
 void f()
 {
    j = 0; // works as expected
    k = 0; // fail
 }
 private:
 __gshared int j;
 extern(C++, ns) __gshared int k;

 Error: module x variable x.ns.k is private
https://issues.dlang.org/show_bug.cgi?id=15578 This is not a forward reference bug, it happens even if 'k' is declared before 'f()'. The workaround is simple: either comment out the 'private' or add 'public' in front of the declaration of 'k'.
Jan 18
next sibling parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 18 January 2016 at 18:45, Walter Bright via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 1/17/2016 9:32 PM, Manu via Digitalmars-d wrote:
 void f()
 {
    j = 0; // works as expected
    k = 0; // fail
 }
 private:
 __gshared int j;
 extern(C++, ns) __gshared int k;

 Error: module x variable x.ns.k is private
https://issues.dlang.org/show_bug.cgi?id=15578 This is not a forward reference bug, it happens even if 'k' is declared before 'f()'. The workaround is simple: either comment out the 'private' or add 'public' in front of the declaration of 'k'.
I realise this isn't forward referencing. It's just the next one I hit. I have rolled with that workaround, but it's not a great workaround. I'd suggest it needs fixing.
Jan 18
parent Walter Bright <newshound2 digitalmars.com> writes:
On 1/18/2016 6:09 AM, Manu via Digitalmars-d wrote:
 I'd suggest it needs fixing.
I agree. I suggested the workaround so you wouldn't be blocked by it.
Jan 18
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 1/18/2016 12:45 AM, Walter Bright wrote:
    https://issues.dlang.org/show_bug.cgi?id=15578
https://github.com/D-Programming-Language/dmd/pull/5358
Jan 19
prev sibling parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 18 January 2016 at 15:32, Manu <turkeyman gmail.com> wrote:
 On 15 January 2016 at 12:25, Walter Bright via Digitalmars-d
 <digitalmars-d puremagic.com> wrote:
 On 1/14/2016 6:24 PM, Walter Bright wrote:
 On 1/13/2016 9:39 PM, Walter Bright wrote:
    https://issues.dlang.org/show_bug.cgi?id=15565
https://issues.dlang.org/show_bug.cgi?id=15565
I meant: https://github.com/D-Programming-Language/dmd/pull/5351
Confirm that problem is solved in latest daily. Next one: void f() { j = 0; // works as expected k = 0; // fail } private: __gshared int j; extern(C++, ns) __gshared int k;
 Error: module x variable x.ns.k is private
Next problem: I'm noticing some differences in struct layout between C++ and D. I'm doing tests by making some classes, putting members in between the locations I expect vtable pointers to be placed, and then comparing the offsets of the members. This is what I'm seeing: In C++: class Base { virtual ~Base() {} size_t x; }; class Interface { virtual Method() = 0; }; class Derived : public Base, public Interface { size_t y; }; In C++, Derived is: { void *__Base_vtable; size_t x; void *__Interface_vtable; size_t y; } This is as I expect. ------------------- D: extern(C++) class Base { ~this() {} size_t x; } extern(C++) interface Interface { abstract Method(); } extern(C++) class Derived : Base, Interface { size_t y; } Derived appears to be: { void *__Base_vtable; size_t x; size_t y; } So, D seems to think 'y' is where Interface_vtable should be... I'm not sure where D thinks the Interface_vtable pointer actually is. What's interesting though, is that I can call 'Method' introduced by Interface, D does try and call something... which means it must get a vtable pointer somewhere, but it crashes on a bad function pointer, so something goes wrong. Digging into the bad virtual call, I get this: (Note, my test case is not exactly what's above; in this test, Interface has a few functions and I'm calling the 4th one in the vtable) 00007FF72DB7381B mov rbx,qword ptr [this] // rbx is 'this' 00007FF72DB7381F mov rcx,qword ptr [rbx+10h] // rcx is [this+10h], which is actually the proper location for Interface_vtable, contrary to what I found above Surprisingly, this looks good. rcx is Interface_vtable, and it found it at the location I expect, which means my test above was lying to me about the location of 'y'. But here it gets a little weird... 00007FF72DB73823 mov rcx,qword ptr [rcx] // what's this? ie, rcx = rcx[0] rcx is now the first function pointer in the vtable; NOT the function I'm calling, which is actually [rcx+18h]! 00007FF72DB73826 sub rsp,20h // nothing of interest 00007FF72DB7382A mov rax,qword ptr [rcx] // dereferencing the function pointer! rax is now the first 8 bytes of program code of the first function in the vtable 00007FF72DB7382D call qword ptr [rax+18h] // calling rax+18h If rax were rcx from the second operation above, 18h is the proper vtable offset of the function I'm trying to call, and this would be correct, but there are 2 bonus dereferences there that shouldn't be. I don't know how interfaces are implemented in D, is this showing some relationship to normal D interface calls? This is certainly not proper extern(C++) behaviour. The offset of y seems confused, and the extra 2 dereferences shouldn't be there.
Jan 18
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/18/2016 12:47 AM, Manu via Digitalmars-d wrote:
 Next problem:
I don't think anyone has tested C++ multiple inheritance against D interfaces. I'm not even sure if you're running C++ on Linux or Windows - and the C++ layout can certainly differ between those compilers. In any case, you can check the layout by running obj2asm on the resulting .o file and looking at the data for the struct initializer. A known problem is that D doesn't put destructors in the vtbl[] for C++ classes, although it should. Also, virtual destructors on Linux 64 consume 2 slots in the vtbl[], which surprised me. Anyhow, things are getting a bit advanced here, and also it has nothing to do with namespaces :-) I'll have to do some more investigating.
Jan 18
next sibling parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 18 January 2016 at 20:24, Walter Bright via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 1/18/2016 12:47 AM, Manu via Digitalmars-d wrote:
 Next problem:
I don't think anyone has tested C++ multiple inheritance against D interfaces. I'm not even sure if you're running C++ on Linux or Windows - and the C++ layout can certainly differ between those compilers.
This particular build is DMD-Win64 tested against against MSC2015-Win64 (I think this is the natural counterpart). I suspect some possibly compiler-agnostic funny business going on here though, since the codegen is dereferencing a vtable at the same location that it seems to think 'y' is living at. I didn't expect this to work. I have no idea how D interfaces are implemented, but I doubted they're the same as C++ multiple inheritance(?). This fairly typical C++ code matches the D multiple inheritance semantics though (ie, single inheritance+interfaces), which is fairly common in C++, COM etc. It would be nice to support this pattern. I don't see any reasons why D should struggle to express it, it's just another case of struct layout difference(?). I am now blocked on this. So hopefully it can be done. I think this is the last hurdle inhibiting CI and cross-platform/compiler testing, or usage of D in our project in general.
 In any case, you can check the layout by running obj2asm on the resulting .o
 file and looking at the data for the struct initializer.
I'll try this tomorrow.
 A known problem is that D doesn't put destructors in the vtbl[] for C++
 classes, although it should. Also, virtual destructors on Linux 64 consume 2
 slots in the vtbl[], which surprised me.
Okay, well we have builds for all common platforms, so maybe we'll hit this when we have working code submit for CI testing. I'm sure I can stress cross-platform compliance on this one when it works.
 Anyhow, things are getting a bit advanced here, and also it has nothing to
 do with namespaces :-) I'll have to do some more investigating.
Yeah, this is now in new territory, since name lookup seems to be working. Shall I spawn a new thread?
Jan 18
parent Walter Bright <newshound2 digitalmars.com> writes:
On 1/18/2016 6:46 AM, Manu via Digitalmars-d wrote:
 Yeah, this is now in new territory, since name lookup seems to be working.
 Shall I spawn a new thread?
A good idea. This one has run its course.
Jan 18
prev sibling parent Max Samukha <maxsamukha gmail.com> writes:
On Monday, 18 January 2016 at 10:24:28 UTC, Walter Bright wrote:

 A known problem is that D doesn't put destructors in the vtbl[] 
 for C++ classes, although it should. Also, virtual destructors 
 on Linux 64 consume 2 slots in the vtbl[], which surprised me.
One is for the destructor, the other - for the destructor and delete.
Jan 18
prev sibling parent reply Daniel Murphy <yebbliesnospam gmail.com> writes:
On 13/01/2016 5:51 PM, Walter Bright wrote:
 If you like:

      extern (C++) {
          int a;
          extern (C++,ns) {
              int a;
          }
      }

 The whole point of scoped names is to be able to do this.
The whole point is meant to be linking to C++ symbols inside namespaces. Nobody wants conflicting symbols in a module, and nobody wants to cram all of their C++ namespace bindings inside a single D source file to avoid getting namespace symbol conflicts.
Jan 16
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/16/2016 6:26 AM, Daniel Murphy wrote:
 Nobody
 wants conflicting symbols in a module, and nobody wants to cram all of their
C++
 namespace bindings inside a single D source file to avoid getting namespace
 symbol conflicts.
D's namespace system does not suffer from those faults.
Jan 16
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 01/16/2016 08:09 PM, Walter Bright wrote:
 On 1/16/2016 6:26 AM, Daniel Murphy wrote:
 Nobody
 wants conflicting symbols in a module, and nobody wants to cram all of
 their C++
 namespace bindings inside a single D source file to avoid getting
 namespace
 symbol conflicts.
D's namespace system does not suffer from those faults.
Why not?
Jan 16
parent Walter Bright <newshound2 digitalmars.com> writes:
On 1/16/2016 4:35 PM, Timon Gehr wrote:
 On 01/16/2016 08:09 PM, Walter Bright wrote:
 On 1/16/2016 6:26 AM, Daniel Murphy wrote:
 Nobody
 wants conflicting symbols in a module, and nobody wants to cram all of
 their C++
 namespace bindings inside a single D source file to avoid getting
 namespace
 symbol conflicts.
D's namespace system does not suffer from those faults.
Why not?
It's come up multiple times in this thread and I've answered it multiple times.
Jan 16
prev sibling parent reply Daniel Murphy <yebbliesnospam gmail.com> writes:
On 17/01/2016 6:09 AM, Walter Bright wrote:
 On 1/16/2016 6:26 AM, Daniel Murphy wrote:
 Nobody
 wants conflicting symbols in a module, and nobody wants to cram all of
 their C++
 namespace bindings inside a single D source file to avoid getting
 namespace
 symbol conflicts.
D's namespace system does not suffer from those faults.
Sure it does. Here's the situation: I have two C++ headers in a library: library\a.h: namespace "mylib" { void funca() { ... } } library\b.h: namespace "mylib" { void funcb() { ... } } I want to create D bindings and keep a similar import layout. So I make: module library.a; extern(C++, mylib) void funca(); and module library.b; extern(C++, mylib) void funcb(); And now I have two library namespace symbols I never wanted. I just wanted to mangle the same as the C++ symbols. D's module system already takes care of resolving conflicts. So now we have two public symbols called 'mylib', and because they conflict they can't be used to disambiguate eg 'someotherlib.funca' with 'library.a.funca'. The only advantage of the current system I've seen presented is that you can now have multiple conflicting symbols in the same module. I can see how that's useful in C++, but I don't think it helps _binding_ to C++ at all. Or how it's worth the mess the extra symbols cause.
Jan 17
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/17/2016 3:55 AM, Daniel Murphy wrote:
 So now we have two public symbols called 'mylib', and because they conflict
they
 can't be used to disambiguate eg 'someotherlib.funca' with 'library.a.funca'.
Consider these two C++ files: ------file 1------------- namespace (X) { int fooa() { ... } ------file 2------------- namespace (X) { int fooa() { ... } ------------------------- You'll get a multiply defined symbol error for X.fooa() from the linker. When using namespaces in D, the "one definition rule" needs to be followed just as in C++ for the same reason. However, in D, you CAN do the following: -----module M----------- extern (C++,X) { int fooa(); } -----module N----------- extern (C++,X) { int fooa(); } ------------------------ and yes, M.X.fooa() will wind up referring to the same externally defined symbol X::fooa() as N.X.fooa(). Because, as I said multiple times, namespaces in D affect the name mangling in a C++ way while doing symbol lookup in the D way. Note that extern(C) { ... } in D works EXACTLY the same way.
Jan 17
next sibling parent reply jmh530 <john.michael.hall gmail.com> writes:
On Sunday, 17 January 2016 at 19:47:46 UTC, Walter Bright wrote:
 and yes, M.X.fooa() will wind up referring to the same 
 externally defined symbol X::fooa() as N.X.fooa().
Just for clarification. Suppose instead of file2 having fooa, it has foob, so there is no conflict within X as to the names. Even in this case, I would have to call fooa and foob with M.X.fooa() and N.X.foob(). I couldn't use X.fooa() and X.foob(). However, suppose only file1 exists. Then, I could call fooa as X.fooa() or M.X.fooa().
Jan 17
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/17/2016 6:16 PM, jmh530 wrote:
 On Sunday, 17 January 2016 at 19:47:46 UTC, Walter Bright wrote:
 and yes, M.X.fooa() will wind up referring to the same externally defined
 symbol X::fooa() as N.X.fooa().
Just for clarification. Suppose instead of file2 having fooa, it has foob, so there is no conflict within X as to the names. Even in this case, I would have to call fooa and foob with M.X.fooa() and N.X.foob(). I couldn't use X.fooa() and X.foob(). However, suppose only file1 exists. Then, I could call fooa as X.fooa() or M.X.fooa().
Yes. Or, in the last case, even just fooa().
Jan 17
parent jmh530 <john.michael.hall gmail.com> writes:
On Monday, 18 January 2016 at 03:58:35 UTC, Walter Bright wrote:
 Yes. Or, in the last case, even just fooa().
It also seems to work if I combine the M and N D packages in that case.
Jan 17
prev sibling parent reply Daniel Murphy <yebbliesnospam gmail.com> writes:
On 18/01/2016 6:47 AM, Walter Bright wrote:
 On 1/17/2016 3:55 AM, Daniel Murphy wrote:
 So now we have two public symbols called 'mylib', and because they
 conflict they
 can't be used to disambiguate eg 'someotherlib.funca' with
 'library.a.funca'.
Consider these two C++ files: ------file 1------------- namespace (X) { int fooa() { ... } ------file 2------------- namespace (X) { int fooa() { ... } ------------------------- You'll get a multiply defined symbol error for X.fooa() from the linker. When using namespaces in D, the "one definition rule" needs to be followed just as in C++ for the same reason. However, in D, you CAN do the following: -----module M----------- extern (C++,X) { int fooa(); } -----module N----------- extern (C++,X) { int fooa(); } ------------------------ and yes, M.X.fooa() will wind up referring to the same externally defined symbol X::fooa() as N.X.fooa(). Because, as I said multiple times, namespaces in D affect the name mangling in a C++ way while doing symbol lookup in the D way. Note that extern(C) { ... } in D works EXACTLY the same way.
So???? Why make extern(C++, namespace) introduce a new symbol? Why not just let it change ONLY mangling and use modules to organize symbols and resolve conflicts?
Jan 19
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/19/2016 12:42 AM, Daniel Murphy wrote:
 So???? Why make extern(C++, namespace) introduce a new symbol? Why not just let
 it change ONLY mangling and use modules to organize symbols and resolve
conflicts?
1. Because a namespace is a scope, and is expected to act like one. 2. So names in different namespaces will not conflict. 3. So names in namespaces can be referenced as: std.exception as one would expect. As the length of this thread testifies, this has been discussed at length already.
Jan 19
next sibling parent Daniel Murphy <yebbliesnospam gmail.com> writes:
On 19/01/2016 7:54 PM, Walter Bright wrote:
 On 1/19/2016 12:42 AM, Daniel Murphy wrote:
 So???? Why make extern(C++, namespace) introduce a new symbol? Why not
 just let
 it change ONLY mangling and use modules to organize symbols and
 resolve conflicts?
1. Because a namespace is a scope, and is expected to act like one.
But I don't want a namespace scope, I want to bind to a symbol in a C++ namespace.
 2. So names in different namespaces will not conflict.
They won't conflict if they're put in different modules.
 3. So names in namespaces can be referenced as:

      std.exception

 as one would expect.
I think the alternative of just referring to it as stdcpp.exception is just fine. Or better.
 As the length of this thread testifies, this has been discussed at
 length already.
My summation of this thread is that very few agree with your design. I recall the same thing of the thread we had before it was introduced. I'll admit that it's probably possible to bind to C++ libraries using the current feature, clumsy as it is.
Jan 19
prev sibling parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 19 January 2016 at 18:54, Walter Bright via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 1/19/2016 12:42 AM, Daniel Murphy wrote:
 So???? Why make extern(C++, namespace) introduce a new symbol? Why not
 just let
 it change ONLY mangling and use modules to organize symbols and resolve
 conflicts?
1. Because a namespace is a scope, and is expected to act like one.
There is absolutely no such expectation. Please take a poll of interested parties if you want to make this argument.
 2. So names in different namespaces will not conflict.
Instead, the namespaces themselves conflict... in every single module! Worse yet, they tend to conflict with the top-level package name, which is terminal for the design. You're taking one extremely unlikely possibility with a simple and obvious solution, and replacing it with a situation where there is conflict in every single module. ns.symbol isn't a useful statement since ns is always in conflict, necessitating x.y.ns.symbol. The necessary disambiguation via full module name justification makes the redundancy of the namespace plain, but we gain such awkward problems in its wake: * namespace names conflict with the D top-level package name (expect, vast majority of cases) * there is more than 1 module (expect, vast majority of cases) * namespace names conflict with D keywords * scanning meta code now needs new tricks to recurse into namespaces (are there __traits even available for this?) * existing/established reflection meta fails when namespaces are present, requires otherwise unnecessary retrofit with additional logic As soon as you must prefix 'x.y' (very likely), the namespace has completely failed at its soul task, and remains nothing more than a nuisance. Let us opt-in if you want this behaviour. It shouldn't be default.
 3. So names in namespaces can be referenced as:

     std.exception

 as one would expect.
Except this rarely works. This expression fails because namespaces require full module justification (ie, stdcpp.exception.std.exception), since they are virtually always in conflict. This behaviour is NOT what one would expect, and can only lead to annoyance or confusion. C++ namespaces span entire projects, they aren't self-contained in individual modules. So, namespace conflict is certain; I invoked it within seconds of attempting to use this feature, whereas the niche case the whole design attempts to prevent is extremely unlikely; I've never encountered it in my career as a C++ programmer. You have presented no other justification for the design than an extremely unlikely case with a trivial workaround, and instead forced that we require various other horrible workarounds as consequence which are almost guaranteed to occur. How can you possibly balance this design decision? C++ namespaces aren't like a D scope, they're more like a D package. There's not a separate instance of the C++ namespace in each object file, there's just one that spans the whole project, just like the top-level package name in D which all modules beneath are a member of.
 As the length of this thread testifies, this has been discussed at length
 already.
No it hasn't. I don't feel like it's been discussed at all. I've explicitly asked both you and Andrei to justify the design several times, no less than 5, and you haven't responded a single time other than repeating these same points without providing any support or evidence. Andrei deliberately dodged the request, replying with something like "the best way to move forwards is to present code that demonstrates bugs". Neither of you appear to be willing to engage in discussion relating to the design, or how it's flawed and pointless. It looks like you understand there's no objective justification for the design. I suspect you just don't want to change it now it's in.
Jan 19
next sibling parent reply rsw0x <anonymous anonymous.com> writes:
On Tuesday, 19 January 2016 at 13:56:54 UTC, Manu wrote:
 ...
Sorry for the noise, but this is a very long thread. Can someone just summarize how C++ namespaces work when interfacing with D? I assumed they just behaved exactly like D modules do, is this wrong?
Jan 19
parent reply Chris Wright <dhasenan gmail.com> writes:
On Tue, 19 Jan 2016 14:15:26 +0000, rsw0x wrote:

 On Tuesday, 19 January 2016 at 13:56:54 UTC, Manu wrote:
 ...
Sorry for the noise, but this is a very long thread. Can someone just summarize how C++ namespaces work when interfacing with D? I assumed they just behaved exactly like D modules do, is this wrong?
You write: module urho3d.core; extern(C++, Urho3D) { extern(C++, Core) { class Context {} } } You can use this like: module foo; import urho3d.core; Context context; // unqualified just works urho3d.core.Context c2; // module-qualified; just works Urho3D.Core.Context c3; // C++ namespaces work too urho3d.core.Urho3D.Core.Context c4; // My eyes! You might sometimes want to use the C++ namespacess when you think it's clearer, but in general you want to ignore them. That's because, if you import two modules that both use the same C++ namespace, you get ambiguous lookup results. When you go to perform a lookup, let's say for Urho3D.Engine.Engine, the compiler sees an `Urho3D` symbol in module urho3d.core. But it also sees an `Urho3D` symbol in module urho3d.engine. That's ambiguous, so it issues a compilation error. This might lead you to conclude that you need to give your D modules different names than the C++ namespaces they wrap, to avoid ambiguities. But it does in fact work as you expect. I believe the D module is given priority -- if you're so inclined, you can write such things as `std.vector.std.vector v` and it just works. The more I look into this, the more I'm impressed by how well it works. I'm kind of surprised that people are insisting on complaining that there's an additional namespace that's trivial to ignore, and they want not to have the option of using C++ namespaces. I mean, that might be a *little* cleaner, but it's certainly not where I'd make my Waterloo.
Jan 19
parent reply David Nadlinger <code klickverbot.at> writes:
On Tuesday, 19 January 2016 at 20:03:47 UTC, Chris Wright wrote:
 I'm kind of surprised that people are insisting on complaining 
 that there's an additional namespace that's trivial to ignore 
 […]
That's not what's happening here. At least when this thread was started, it was not at all possible to just blissfully ignore them. You'd run into all kinds of weird issues, as Manu pointed out – many of which have hopefully been fixed by Walter in the meantime. Apart from this, the argument still stands that the whole concept of having named scopes for C++ namespaces increases the size of the language for no good reason (yes, I'm aware that this increase might be trivial in terms of internal implementation, but it's not from a user's perspective). — David
Jan 19
next sibling parent Chris Wright <dhasenan gmail.com> writes:
On Tue, 19 Jan 2016 20:35:17 +0000, David Nadlinger wrote:

 On Tuesday, 19 January 2016 at 20:03:47 UTC, Chris Wright wrote:
 I'm kind of surprised that people are insisting on complaining that
 there's an additional namespace that's trivial to ignore […]
That's not what's happening here. At least when this thread was started, it was not at all possible to just blissfully ignore them.
I'm testing with 2.069.2, which was released on 3 December. This thread started on 3 January. Looking back through the archives, it seems like Manu's initial complaint implied that C++ namespace functionality was entirely broken, whereas a few posts later it came out that it usually works but there are some potentially complex cases that break. I'd understand if people were saying that C++ namespaces as D scopes are currently broken and it's simpler to remove them as D scopes than to fix them. But I'm seeing people saying that this is just a bad feature in the beginning, something that is a blight upon the language, and removing it in the absence of bugs is not only right but essential.
Jan 19
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/19/2016 12:35 PM, David Nadlinger wrote:
You'd run into all kinds of
 weird issues, as Manu pointed out – many of which have hopefully been fixed
by
 Walter in the meantime.
Please read the thread. I fixed them and posted here that they were fixed. Please do not conflate implementation bugs with the design.
Jan 19
next sibling parent Chris Wright <dhasenan gmail.com> writes:
On Tue, 19 Jan 2016 13:46:07 -0800, Walter Bright wrote:

 On 1/19/2016 12:35 PM, David Nadlinger wrote:
You'd run into all kinds of
 weird issues, as Manu pointed out – many of which have hopefully been
 fixed by Walter in the meantime.
Please read the thread. I fixed them and posted here that they were fixed. Please do not conflate implementation bugs with the design.
Thank you for your patience.
Jan 19
prev sibling parent David Nadlinger <code klickverbot.at> writes:
On Tuesday, 19 January 2016 at 21:46:07 UTC, Walter Bright wrote:
 On 1/19/2016 12:35 PM, David Nadlinger wrote:
You'd run into all kinds of
 weird issues, as Manu pointed out – many of which have 
 hopefully been fixed by
 Walter in the meantime.
Please read the thread. I fixed them and posted here that they were fixed. Please do not conflate implementation bugs with the design.
Before making such statements, it might be prudent to somewhat thoroughly read the message you are referring to. The sentence immediately before the one you quoted reads: "At least when this thread was started, it was not at all possible to just blissfully ignore them." I am not conflating implementation and design – in fact I was precisely pointing out to to Chris that part of the troubles Manu was having is due to implementation issues! — David
Jan 20
prev sibling next sibling parent reply David Nadlinger <code klickverbot.at> writes:
On Tuesday, 19 January 2016 at 13:56:54 UTC, Manu wrote:
 On 19 January 2016 at 18:54, Walter Bright via Digitalmars-d
 As the length of this thread testifies, this has been 
 discussed at length already.
No it hasn't. I don't feel like it's been discussed at all. I've explicitly asked both you and Andrei to justify the design several times, no less than 5, and you haven't responded a single time other than repeating these same points without providing any support or evidence. Andrei deliberately dodged the request, replying with something like "the best way to move forwards is to present code that demonstrates bugs". Neither of you appear to be willing to engage in discussion relating to the design, or how it's flawed and pointless. It looks like you understand there's no objective justification for the design. I suspect you just don't want to change it now it's in.
While I am not in the mood for mudslinging or making a heated discussion out of this, I have to agree with Daniel and Manu here. If I remember correctly, you never really provided any justification (including during the original discussion back when the feature was introduced) as to why just using the normal means of name resolution and disambiguation in D – the module system – is not good enough for this. It's fine if you just say "I had a hunch that the added complexity would be worth it by making some situations more convenient, even though I can't provide a concrete example". Of course that might not be particularly persuasive, but it's your call in the end. But if you keep dodging the question, this discussion will never come to an end. — David
Jan 19
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/19/2016 12:29 PM, David Nadlinger wrote:
 It's fine if you just say "I had a hunch that the added complexity would be
 worth it by making some situations more convenient, even though I can't provide
 a concrete example". Of course that might not be particularly persuasive, but
 it's your call in the end. But if you keep dodging the question, this
discussion
 will never come to an end.
I have answered "why not use modules" many times. I have answered the other questions, too. Please do not conflate not agreeing with my answers with not responding.
Jan 19
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/19/2016 1:40 PM, Walter Bright wrote:
 On 1/19/2016 12:29 PM, David Nadlinger wrote:
 It's fine if you just say "I had a hunch that the added complexity would be
 worth it by making some situations more convenient, even though I can't provide
 a concrete example". Of course that might not be particularly persuasive, but
 it's your call in the end. But if you keep dodging the question, this
discussion
 will never come to an end.
I have answered "why not use modules" many times. I have answered the other questions, too. Please do not conflate not agreeing with my answers with not responding.
Oh what the hell. I'll answer it one last time: 1. C++ has namespaces. They went and invented a whole 'nother thing called modules. Evidently not even they think that modules and namespaces are the same thing. 2. Multiple modules cannot have the same name in D. C++ practice is to litter code with namespaces using the same name. 3. Modules have ModuleInfos, static constructors/destructors, etc. These do not make obvious sense for namespaces. 4. Modules and files have a 1:1 correspondence. This does not work for namespaces. 5. "extern (C++) module std" ? Ugh. 6. Modules do not nest. Namespaces nest. 7. Module semantics are independent of where they are imported. Not so for namespaces. I.e. if modules were bludgeoned into being namespaces, there would be such a list of special cases and confusions and exceptions and awkward crap you'd be far, far better off having namespace as a SEPARATE feature, because that's what they'd wind up being anyway, even if they were named "modules".
Jan 19
next sibling parent =?UTF-8?Q?Tobias=20M=C3=BCller?= <troplin bluewin.ch> writes:
Walter Bright <newshound2 digitalmars.com> wrote:
 Oh what the hell. I'll answer it one last time:
 
 1. C++ has namespaces. They went and invented a whole 'nother thing called 
 modules. Evidently not even they think that modules and namespaces are the
same 
 thing.
D has modules, C++ has namespace. Why do you introduce yet another concept? You call it named scope but for consumers it behaves like a module...
 2. Multiple modules cannot have the same name in D. C++ practice is to litter 
 code with namespaces using the same name.
It doesn't help if they are just imported as modules in disguise.
 3. Modules have ModuleInfos, static constructors/destructors, etc. These do
not 
 make obvious sense for namespaces.
 
 4. Modules and files have a 1:1 correspondence. This does not work for
namespaces.
 
 5. "extern (C++) module std" ? Ugh.
Nobody has ever suggested this. mod and extern should be completely separate.
 6. Modules do not nest. Namespaces nest.
 
 7. Module semantics are independent of where they are imported. Not so for 
 namespaces.
 
 I.e. if modules were bludgeoned into being namespaces, there would be such a 
 list of special cases and confusions and exceptions and awkward crap you'd be 
 far, far better off having namespace as a SEPARATE feature, because that's
what 
 they'd wind up being anyway, even if they were named "modules".
mod should not imply a C++ namespace and extern(C++, ns) should not introduce a named scope. This gives you maximal flexibility with minimal complexity. You could import symbols from different namespaces to the same module and you could import symbols from the same namespace to different modules. Modules and namespaces would be completely independent. I'd even count all those points above as arguments _against_ the current design. Tobi
Jan 19
prev sibling next sibling parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 20 January 2016 at 08:14, Walter Bright via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 Oh what the hell. I'll answer it one last time:

 1. C++ has namespaces. They went and invented a whole 'nother thing called
 modules. Evidently not even they think that modules and namespaces are the
 same thing.
You admit that modules supersede namespaces. We have modules, we use modules as standard practise. We don't need, or want, anything like namespaces.
 2. Multiple modules cannot have the same name in D.
I'm not sure what situation you're imagining where modules would be created with the same names...?
 C++ practice is to litter code with namespaces using the same name *.
* among different includes... it is natural to reflect the C++ include tree as D modules, and this naturally gives everything expected scope separation.
From there, the only requirement is that we can link.
 3. Modules have ModuleInfos, static constructors/destructors, etc. These do
 not make obvious sense for namespaces.
I'm not sure why you're introducing these concepts...? This has nothing to do with name mangling. It has never been proposed that namespaces have anything to do with modules, only that modules make namespaces irrelevant.
 4. Modules and files have a 1:1 correspondence. This does not work for
 namespaces.
I'm not sure what your point here is. Are you arguing that C++ namespaces aren't expressible in D, because nothing can span modules? Of course, I agree completely. This is a good argument against trying to simulate C++ namespaces in D.
 5. "extern (C++) module std" ? Ugh.
Where did you pull that from? Nobody has ever suggested anything like that as far as I know. Naturally, I strongly object to this too.
 6. Modules do not nest. Namespaces nest.
I'm not quite sure how this is an argument, but if we're just making an analogy; modules nest within packages: import x.y.z; Organising the API into packages/modules is the business of the binding author. C++ namespace and/or header directory structure can be easily reproduced in a natural way as D modules. You seem to be approaching from the presumption that namespaces (or an awkward simulation of them) exist in D. These points are irrelevant if the namespace is just for mangling.
 7. Module semantics are independent of where they are imported. Not so for
 namespaces.

 I.e. if modules were bludgeoned into being namespaces,
Nobody has ever suggested anything like this.
 there would be such a
 list of special cases and confusions and exceptions and awkward crap you'd
 be far, far better off having namespace as a SEPARATE feature, because
 that's what they'd wind up being anyway, even if they were named "modules".
If this is what you're thinking, you've misunderstood literally everything I've ever said on this topic. The feature should be nothing more than this: extern(C++, "ns") int x; x is mangled with "ns". Namespace is a string, no conflict with D names is possible, organisation and disambiguation is the business of the author. Everything past that is needless complexity and causes us problems. The extremely niche case where someone wants to declare 2 symbols with the same name within the same module (in C++, they achieve this using 2 namespaces), is easily solvable in various ways that a normal D user could use to resolve that desire in a pure D program, for instance (but not limited to) putting the second declaration in another module. _all consequent problems_ are abolished instantly, all behaviour is exactly like normal D code, no surprises, no edge cases. The code to do this must be a small fraction of the code required to implement the feature as it is today.
Jan 19
next sibling parent reply deadalnix <deadalnix gmail.com> writes:
On Wednesday, 20 January 2016 at 07:51:27 UTC, Manu wrote:
 1. C++ has namespaces. They went and invented a whole 'nother 
 thing called modules. Evidently not even they think that 
 modules and namespaces are the same thing.
You admit that modules supersede namespaces. We have modules, we use modules as standard practise. We don't need, or want, anything like namespaces.
Maybe you don't, but I remain quite confident that being able to mimic the structure of the C++ code in D is valuable. One can create a binding for a library and have it usable in a similar fashion as it is in C++ from D. This makes it nice to people that already know the library, reduce the need for specific doc for the binding, and makes maintenance of the binding much easier as it has the same structure as the mapped C++ lib.
 2. Multiple modules cannot have the same name in D.
I'm not sure what situation you're imagining where modules would be created with the same names...?
How do you plan to map C++'s standard lib ? One giant hundred of thousands of line C++ file ?
 4. Modules and files have a 1:1 correspondence. This does not 
 work for namespaces.
I'm not sure what your point here is. Are you arguing that C++ namespaces aren't expressible in D, because nothing can span modules? Of course, I agree completely. This is a good argument against trying to simulate C++ namespaces in D.
That doesn't make any sense.
 5. "extern (C++) module std" ? Ugh.
Where did you pull that from? Nobody has ever suggested anything like that as far as I know. Naturally, I strongly object to this too.
Well you still have to explain how the C++'s standard library is going to be mapped with D module emulating C++'s namespaces.
 7. Module semantics are independent of where they are 
 imported. Not so for namespaces.

 I.e. if modules were bludgeoned into being namespaces,
Nobody has ever suggested anything like this.
You did that quite a few time yourself.
 there would be such a
 list of special cases and confusions and exceptions and 
 awkward crap you'd
 be far, far better off having namespace as a SEPARATE feature, 
 because
 that's what they'd wind up being anyway, even if they were 
 named "modules".
If this is what you're thinking, you've misunderstood literally everything I've ever said on this topic. The feature should be nothing more than this: extern(C++, "ns") int x; x is mangled with "ns". Namespace is a string, no conflict with D names is possible, organisation and disambiguation is the business of the author. Everything past that is needless complexity and causes us problems. The extremely niche case where someone wants to declare 2 symbols with the same name within the same module (in C++, they achieve this using 2 namespaces), is easily solvable in various ways that a normal D user could use to resolve that desire in a pure D program, for instance (but not limited to) putting the second declaration in another module.
The WHOLE point of namespace in C++ is to be able to have symbol with the same name and not conflict. Now you could say, put them in different modules and use the modules to disambiguate, but then you'd use the C++ library in quite a different way, meaning you need to write new doc and make the work of the binding maintainer harder.
 _all consequent problems_ are abolished instantly, all 
 behaviour is
 exactly like normal D code, no surprises, no edge cases.
 The code to do this must be a small fraction of the code 
 required to
 implement the feature as it is today.
I don't expect so. All the resolution mechanisms required here already exists in some form already. DMD may be kludged, but come on, once something is defined a way, it is not possible to change it, so please disregard DMD specificity here.
Jan 20
parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 20 January 2016 at 18:37, deadalnix via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Wednesday, 20 January 2016 at 07:51:27 UTC, Manu wrote:
 1. C++ has namespaces. They went and invented a whole 'nother thing
 called modules. Evidently not even they think that modules and namespaces
 are the same thing.
You admit that modules supersede namespaces. We have modules, we use modules as standard practise. We don't need, or want, anything like namespaces.
Maybe you don't, but I remain quite confident that being able to mimic the structure of the C++ code in D is valuable. One can create a binding for a library and have it usable in a similar fashion as it is in C++ from D.
How is that not possible with normal use of modules?
 This makes it nice to people that already know the library, reduce the need
 for specific doc for the binding, and makes maintenance of the binding much
 easier as it has the same structure as the mapped C++ lib.
I'm not sure how maintaining this structure has anything to do with namespaces. The only requirement for a lib to feel natural is to map each header to a module of the same name. When I look up the qt doc, I see: #include <widget.h> Which intuitively maps to: import qt.widget; The author requires some latitude in such mapping, eg: #include <SDL_image.h> Obviously unsavoury in D mapped verbatim, it would likely become: import sdl.image; You may consider this a drastic deviation from the doc, but I expect D users would universally prefer this.
 2. Multiple modules cannot have the same name in D.
I'm not sure what situation you're imagining where modules would be created with the same names...?
How do you plan to map C++'s standard lib ? One giant hundred of thousands of line C++ file ?
Surely it would map by file. #include <vector> -> import stl.vector; #include <map> -> import stl.map; #include <string> -> import stl.string; Perhaps 'stl' may be something else, 'std' is an unfortunate conflict with phobos, but this is unique to this case.
 7. Module semantics are independent of where they are imported. Not so
 for namespaces.

 I.e. if modules were bludgeoned into being namespaces,
Nobody has ever suggested anything like this.
You did that quite a few time yourself.
No, I really *really* didn't. It seems I have a habit of being completely misunderstood.
 The WHOLE point of namespace in C++ is to be able to have symbol with the
 same name and not conflict.
D is extremely good at this already.
 Now you could say, put them in different modules and use the modules to
 disambiguate, but then you'd use the C++ library in quite a different way,
 meaning you need to write new doc and make the work of the binding
 maintainer harder.
This doesn't make sense at all. How is that using it in a completely different way? I'd suggest it's the only possible way to make it feel the same. It's a no-brainer for the binding author, copy and rename .h files to .d, then regex until finished. What case is there where a C++ lib distributing its symbols naturally among modules named accordingly with the original include's would cause confusion when compared against the C++ docs? Doc says '#include <libname/feature.h>', I'll 'import libname.feature;' Nothing could be more natural than this. As a bonus, the project's C++ namespace 'libname' is already present in the fully qualified name, it's the top level package! No point repeating that as 'libname.feature.libname.symbol'.
Jan 20
next sibling parent Edwin van Leeuwen <edder tkwsping.nl> writes:
On Wednesday, 20 January 2016 at 12:47:44 UTC, Manu wrote:

 No, I really *really* didn't.
 It seems I have a habit of being completely misunderstood.
Just for your information, I understand what you mean Manu :) (and agree with you). I guess it might be helpful if you could spell out (in pseudo code) how you would wrap part of the c++ std library (std.vector and std.map?) in your proposed way and how you have to do it now. This might help to highlight your point.
Jan 20
prev sibling next sibling parent reply Simen Kjaeraas <simen.kjaras gmail.com> writes:
On Wednesday, 20 January 2016 at 12:47:44 UTC, Manu wrote:
 2. Multiple modules cannot have the same name in D.
I'm not sure what situation you're imagining where modules would be created with the same names...?
How do you plan to map C++'s standard lib ? One giant hundred of thousands of line C++ file ?
Surely it would map by file. #include <vector> -> import stl.vector; #include <map> -> import stl.map; #include <string> -> import stl.string; Perhaps 'stl' may be something else, 'std' is an unfortunate conflict with phobos, but this is unique to this case.
I believe deadalnix here meant something like this: import stl.vector; import mylib.vector; Vector a; // Ambiguous: could be from mylib or stl stl.Vector b; // Error: no such class stl.Vector stl.vector.Vector c; // Works, but requires extra typing Which with working namespaces might allow case b to work. -- Simen
Jan 20
parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 21 January 2016 at 01:32, Simen Kjaeraas via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Wednesday, 20 January 2016 at 12:47:44 UTC, Manu wrote:
 2. Multiple modules cannot have the same name in D.
I'm not sure what situation you're imagining where modules would be created with the same names...?
How do you plan to map C++'s standard lib ? One giant hundred of thousands of line C++ file ?
Surely it would map by file. #include <vector> -> import stl.vector; #include <map> -> import stl.map; #include <string> -> import stl.string; Perhaps 'stl' may be something else, 'std' is an unfortunate conflict with phobos, but this is unique to this case.
I believe deadalnix here meant something like this: import stl.vector; import mylib.vector; Vector a; // Ambiguous: could be from mylib or stl stl.Vector b; // Error: no such class stl.Vector stl.vector.Vector c; // Works, but requires extra typing
Okay let me tweak your code: import stl.vector; import stl.string; // one more thing; when do you ever only import a single module? import mylib.vector; Vector a; // Ambiguous: could be from mylib or stl stl.Vector b; // Error: this wouldn't work, becase stl could be stl.vector.stl or stl.map.stl stl.vector.Vector c; // This is what a D programmer expects, exactly like every other conflict resolution in D ever, but it doesn't work either So, it is proposed that people desire to type only stl.Vector to disambiguate, assuming that 'stl' is a named namespace. This only works in the rare case that you only import one single module. This is almost never true! As soon as you import 2 modules, stl.vector, stl.string for instance, 'stl' is now in conflict, and you require to type: stl.vector.stl.Vector c; // Necessary, and even more extra typing! I am yet to experience a single case of isolated imports... real code that's not a 3 line test case tends to import more than one thing. I also object strongly to the rules being different than every other case of conflict in D that a user has ever experienced.
 Which with working namespaces might allow case b to work.
I hope I've shown how it almost never does, and only makes the situation worse.
Jan 20
parent Simen Kjaeraas <simen.kjaras gmail.com> writes:
On Wednesday, 20 January 2016 at 23:35:31 UTC, Manu wrote:
 On 21 January 2016 at 01:32, Simen Kjaeraas via Digitalmars-d 
 <digitalmars-d puremagic.com> wrote:
 On Wednesday, 20 January 2016 at 12:47:44 UTC, Manu wrote:
 2. Multiple modules cannot have the same name in D.
I'm not sure what situation you're imagining where modules would be created with the same names...?
How do you plan to map C++'s standard lib ? One giant hundred of thousands of line C++ file ?
Surely it would map by file. #include <vector> -> import stl.vector; #include <map> -> import stl.map; #include <string> -> import stl.string; Perhaps 'stl' may be something else, 'std' is an unfortunate conflict with phobos, but this is unique to this case.
I believe deadalnix here meant something like this: import stl.vector; import mylib.vector; Vector a; // Ambiguous: could be from mylib or stl stl.Vector b; // Error: no such class stl.Vector stl.vector.Vector c; // Works, but requires extra typing
Okay let me tweak your code: import stl.vector; import stl.string; // one more thing; when do you ever only import a single module? import mylib.vector; Vector a; // Ambiguous: could be from mylib or stl stl.Vector b; // Error: this wouldn't work, becase stl could be stl.vector.stl or stl.map.stl stl.vector.Vector c; // This is what a D programmer expects, exactly like every other conflict resolution in D ever, but it doesn't work either
[snip]
 Which with working namespaces might allow case b to work.
I hope I've shown how it almost never does, and only makes the situation worse.
I'm playing devil's advocate here, since I fully agree with you that there is absolutely no need for C++ namespaces in D, and that the cost in language complexity is too high. Suppose that case b above worked, though - instead of a conflict, lookup would basically merge namespaces with the same name, and only conflict if there are multiple definitions that are not namespaces. On the one hand, I hope that's how it's supposed to work, otherwise it's just silly. On the other hand, that's a clear break with D's current lookup rules, and for what I consider very, very little benefit. -- Simen
Jan 20
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/20/2016 4:47 AM, Manu via Digitalmars-d wrote:
 As a bonus, the project's C++ namespace 'libname' is already present
 in the fully qualified name, it's the top level package! No point
 repeating that as 'libname.feature.libname.symbol'.
You can always write a module that all it does is import a bunch of other modules, with a bunch of aliases which can be used to make those imports appear in another namespace: ----module core.stdcpp.vector---- extern (C++, std) { struct vector { } } ----module core.stdcpp.string---- extern (C++, std) { struct string { } } ----module stl------ private import core.stdcpp.vector; private import core.stdcpp.string; ... extern (C++, std) { alias core.stdcpp.vector.std.vector vector; alias core.stdcpp.string.std.string string; ... } ---module user----- import stl; std.vector v; std.string s;
Jan 20
parent reply tsbockman <thomas.bockman gmail.com> writes:
On Wednesday, 20 January 2016 at 22:13:09 UTC, Walter Bright 
wrote:
 You can always write a module that all it does is import a 
 bunch of other modules, with a bunch of aliases which can be 
 used to make those imports appear in another namespace:

    ----module core.stdcpp.vector----
    extern (C++, std) { struct vector { } }

    ----module core.stdcpp.string----
    extern (C++, std) { struct string { } }

    ----module stl------
    private import core.stdcpp.vector;
    private import core.stdcpp.string;
    ...
    extern (C++, std)
    {
       alias core.stdcpp.vector.std.vector vector;
       alias core.stdcpp.string.std.string string;
       ...
    }

    ---module user-----
    import stl;

    std.vector v;
    std.string s;
The thought of needing to do that for (potentially) every single symbol being imported is depressing. What happened to DRY?
Jan 20
parent Walter Bright <newshound2 digitalmars.com> writes:
On 1/20/2016 3:53 PM, tsbockman wrote:
 The thought of needing to do that for (potentially) every single symbol being
 imported is depressing. What happened to DRY?
Since it is completely mechanical, it's an ideal candidate for writing a metafunction to do it: ----module stl------ private import core.stdcpp.vector; private import core.stdcpp.string; ... extern (C++, std) { mixin(aliasAllNamespaceMembers()); }
Jan 20
prev sibling parent deadalnix <deadalnix gmail.com> writes:
 I'm not sure what situation you're imagining where modules 
 would be created with the same names...?
How do you plan to map C++'s standard lib ? One giant hundred of thousands of line C++ file ?
Surely it would map by file. #include <vector> -> import stl.vector; #include <map> -> import stl.map; #include <string> -> import stl.string; Perhaps 'stl' may be something else, 'std' is an unfortunate conflict with phobos, but this is unique to this case.
But, in this case, I can't have an stl.vector!X which would map to an std::vector<X> . The namespacing of symbol has been completely changed.
 I'd suggest it's the only possible way to make it feel the same.
 It's a no-brainer for the binding author, copy and rename .h 
 files to
 .d, then regex until finished.
That would require to have a similar namespacing, unless extern(C++, name) introduce a symbol called name. Note that the conflict rule can be tuned the same way it is specified for multiple alias this and you get something really nice.
 What case is there where a C++ lib distributing its symbols 
 naturally
 among modules named accordingly with the original include's 
 would
 cause confusion when compared against the C++ docs?
 Doc says '#include <libname/feature.h>', I'll 'import 
 libname.feature;'
 Nothing could be more natural than this.

 As a bonus, the project's C++ namespace 'libname' is already 
 present in the fully qualified name, it's the top level 
 package! No point repeating that as 
 'libname.feature.libname.symbol'.
I think it does make sense to make the C++ namespace "skippable", alias this style, while keeping it around to disambiguate. It is clear that C++ having namespacing and header being decoupled will cause problem if namespaces do not introduce a symbol.
Jan 20
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/19/2016 11:51 PM, Manu via Digitalmars-d wrote:
 You admit
This is where a debate about ideas leaves the rails. This is not a court, nobody has alleged a crime. I want to bring it back on the track. I want to help you be successful with interfacing D with C++. You have posted several bugs with the ns implementation. I have fixed those bugs, and you agreed they were fixed. You wrote there are remaining serious problems with ns. I have no idea what they are. Please post code that illustrates what serious problem(s) you are having.
Jan 20
next sibling parent Daniel N <ufo orbiting.us> writes:
On Wednesday, 20 January 2016 at 08:38:35 UTC, Walter Bright 
wrote:
 On 1/19/2016 11:51 PM, Manu via Digitalmars-d wrote:
 You admit
This is where a debate about ideas leaves the rails. This is not a court, nobody has alleged a crime. I want to bring it back on the track. I want to help you be successful with interfacing D with C++. You have posted several bugs with the ns implementation. I have fixed those bugs, and you agreed they were fixed. You wrote there are remaining serious problems with ns. I have no idea what they are. Please post code that illustrates what serious problem(s) you are having.
Considering all the arguments both recently and when the feature was first implemented, I find it unlikely that everyone will ever agree to one solution. Are there any strong arguments against making the scope *optional*? The cost of implementation should be quite low, both compared to the complexity of the feature itself and the complexity of all the *different* workarounds people already use to hide the symbols.
Jan 20
prev sibling parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 20 January 2016 at 18:38, Walter Bright via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 1/19/2016 11:51 PM, Manu via Digitalmars-d wrote:
 You admit
This is where a debate about ideas leaves the rails. This is not a court, nobody has alleged a crime. I want to bring it back on the track. I want to help you be successful with interfacing D with C++. You have posted several bugs with the ns implementation. I have fixed those bugs, and you agreed they were fixed. You wrote there are remaining serious problems with ns. I have no idea what they are. Please post code that illustrates what serious problem(s) you are having.
I'm blocked by the interface inheritance. I can work-around anything other than that, but there's no way I can progress without being able to call methods. This set of related problems, all have bitten me. -- name.x.d-------------------- module name.x; -- name.y.d-------------------- module name.y; import name.x; extern(C++, name) int x; ------------------------------------ ------------------------------------ extern(C++, delegate) int x; ------------------------------------ You claim this is a problem that must desperately be solved: ------------------------------------ int x; extern(C++, ns) int x; ------------------------------------ The solution arrives at basically the same problem: ------------------------------------ int ns; extern(C++, ns) int x; ------------------------------------ We've just robbed peter to pay paul? Finally, the one that really upsets me, is that scanning reflection needs to be retrofit with new tricks to recurse into namespaces: ------------------------------------ extern(C++, ns) void f(); pragma(msg, __traits(allMembers, mixin(__MODULE__))); ------------------------------------
 tuple("object", "ns")
... f() is not present. By extension of this, extern(C++, ns) declarations are incompatible with every single implementation of scanning reflection I've written in the past 6 years, and everyone else's too. All such code needs to be retrofit with new tricks to recurse into ns. On 20 January 2016 at 18:38, Walter Bright via Digitalmars-d <digitalmars-d puremagic.com> wrote:
 On 1/19/2016 11:51 PM, Manu via Digitalmars-d wrote:
 You admit
This is where a debate about ideas leaves the rails. This is not a court, nobody has alleged a crime. I want to bring it back on the track. I want to help you be successful with interfacing D with C++. You have posted several bugs with the ns implementation. I have fixed those bugs, and you agreed they were fixed. You wrote there are remaining serious problems with ns. I have no idea what they are. Please post code that illustrates what serious problem(s) you are having.
Jan 20
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/20/2016 4:17 AM, Manu via Digitalmars-d wrote:
 -- name.x.d--------------------
 module name.x;
 -- name.y.d--------------------
 module name.y;
 import name.x;
 extern(C++, name) int x;
 ------------------------------------
This won't work any more than: import name.y; struct name { } would. You can't have two different definitions for the same identifier in the same scope, and that's true for any programming language I've heard of.
 ------------------------------------
 extern(C++, delegate) int x;
 ------------------------------------
Yes, we've talked about that. I'm thinking of a solution where it could be written like: extern(C++, delegate_) int x; and the C++ name mangler strips off any trailing _. Note that this problem is NOT resolved by your proposed solution, as this wouldn't work, either: extern(C++) int* delegate(); or any other use of D keywords as C/C++ identifiers. https://issues.dlang.org/show_bug.cgi?id=15587
 You claim this is a problem that must desperately be solved:
 ------------------------------------
 int x;
 extern(C++, ns) int x;
 ------------------------------------

 The solution arrives at basically the same problem:
 ------------------------------------
 int ns;
 extern(C++, ns) int x;
 ------------------------------------

 We've just robbed peter to pay paul?
C++ doesn't allow: int ns; namespace ns { ... } either, so there can never be a need to solve that problem.
 scanning reflection
 needs to be retrofit with new tricks to recurse into namespaces:
 ------------------------------------
 extern(C++, ns) void f();
 pragma(msg, __traits(allMembers, mixin(__MODULE__)));
 ------------------------------------
 tuple("object", "ns")
... f() is not present. By extension of this, extern(C++, ns) declarations are incompatible with every single implementation of scanning reflection I've written in the past 6 years, and everyone else's too. All such code needs to be retrofit with new tricks to recurse into ns.
Seems to me that all that is necessary is to replace: __traits(allMembers, mixin(__MODULE__)) with: getAllMembersIncludingNs(mixin(__MODULE__)) and then write getAllMembersIncludingNS() as a function that recursively adds members of namespaces. After all, the ugly __traits() was always meant to be a building block to be encapsulated by a function that does what is really wanted. I wouldn't call it tricky.
Jan 20
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 01/20/2016 09:56 PM, Walter Bright wrote:
 On 1/20/2016 4:17 AM, Manu via Digitalmars-d wrote:
 -- name.x.d--------------------
 module name.x;
 -- name.y.d--------------------
 module name.y;
 import name.x;
 extern(C++, name) int x;
 ------------------------------------
This won't work ...
The suggestion was to just not introduce a new symbol/scope for the namespace. It would certainly work.
Jan 20
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/20/2016 1:47 PM, Timon Gehr wrote:
 On 01/20/2016 09:56 PM, Walter Bright wrote:
 On 1/20/2016 4:17 AM, Manu via Digitalmars-d wrote:
 -- name.x.d--------------------
 module name.x;
 -- name.y.d--------------------
 module name.y;
 import name.x;
 extern(C++, name) int x;
 ------------------------------------
This won't work ...
The suggestion was to just not introduce a new symbol/scope for the namespace. It would certainly work.
I understand his suggestion. I asked Manu to elaborate what the "serious problems" are. This code snippet doesn't work as it is not supposed to work, but still unknown is what the "serious problem" with it is - and I want to ensure that Manu knows this is not a bug in the implementation.
Jan 20
next sibling parent reply =?UTF-8?Q?Martin_Dra=c5=a1ar?= via Digitalmars-d writes:
Dne 20.1.2016 v 23:01 Walter Bright via Digitalmars-d napsal(a):
 I understand his suggestion. I asked Manu to elaborate what the "serious
 problems" are. This code snippet doesn't work as it is not supposed to
 work, but still unknown is what the "serious problem" with it is - and I
 want to ensure that Manu knows this is not a bug in the implementation.
Bugs in implementation are a separate concern. The "serious" problem is that the decision to have a namespace introduce a new scope needlessly complicates writing D-like interfaces to C++ code, while catering for one specific use-case that is considered niche. Everything in this thread has been repeated at least three times. Yet you still stand by your design decision and offer more or less convoluted ways to deal with it. I guess that at this point it would be great to introduce some hard data. For example, how often would you encounter the problem with the same identifiers distinguished by namespaces, if you tried to interface to some typical C++ libraries. Because, unless you really must have your interface in one file, this should be fairly rare (at least from my experience). Martin
Jan 20
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/20/2016 3:12 PM, Martin Drašar via Digitalmars-d wrote:
 The "serious" problem is
 that the decision to have a namespace introduce a new scope needlessly
 complicates writing D-like interfaces to C++ code, while catering for
 one specific use-case that is considered niche.
Adding a qualifier here and there does not count as serious.
Jan 20
next sibling parent reply Anon <anon anon.anon> writes:
What would you all say to the following proposal (and should I 
make a DIP?)


1. deprecate pragma(mangle)
2. deprecate extern(C++, ns)
3. deprecate  selector()
4. Introduce a better, more general extern() as follows:

extern ( <LanguageIdent> [, <String> ] )

Which would *only* influence mangling and calling conventions. 
Blocks would concatenate their <String>s, with the default value 
for a symbol being its identifier. Whatever the concatenated 
string is then gets run through a language-specific mangler with 
knowledge of the type info. It would be an error for nesting 
blocks to change language. The content of the string would depend 
on the language in question. This would be also extendable beyond 
C, C++, D, and Objective-C to other languages if so desired 
(Rust, Go, C#, etc.) while keeping a uniform syntax and behavior 
regardless of the language being bound.

Some examples:

extern(C) int foo(); // Mangled as "foo"

extern(C, "body") int body_(); // "body"

extern(C++) int foo(); // cppMangleOf("foo")

extern(C++, "body") int body_(); // cppMangleOf("body")

extern(D) int foo(); // "_D3fooFZi" -no module

extern(D, "body") int body_; // "_D4bodyFZi" -no module

extern(C++, "ns::foo") int foo(); // cppMangleOf("ns::foo")

extern(C++, "ns::")
{
     int foo(); // cppMangleOf("ns::foo")

     extern(C++, "body") int body_(); // cppMangleOf("ns::body")

     // I'm unsure of the next two. Both need to be inside an
     // extern(<Lang>) block and would infer the <LanguageIdent>
     // extern("with") int with_(); // cppMangleOf("ns::with")
     // extern(auto, "with") int with_(); // 
cppMangleOf("ns::with")
}

extern(C, "SDL_")
{
     void init(); // "SDL_init"
}

extern(D, "std.ascii.")
{
     // std.ascii.isAlphaNum.mangleof
     bool isAlphaNum(dchar) pure nothrow  nogc  safe bool;
}
Jan 20
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/20/2016 4:51 PM, Anon wrote:
 What would you all say to the following proposal (and should I make a DIP?)
DIPs are always welcome.
Jan 20
parent Anon <anon anon.anon> writes:
On Thursday, 21 January 2016 at 01:37:12 UTC, Walter Bright wrote:
 On 1/20/2016 4:51 PM, Anon wrote:
 What would you all say to the following proposal (and should I 
 make a DIP?)
DIPs are always welcome.
Done. http://forum.dlang.org/post/ldtluvnhuznvbebcbkmk forum.dlang.org
Jan 20
prev sibling parent Marc =?UTF-8?B?U2Now7x0eg==?= <schuetzm gmx.net> writes:
On Thursday, 21 January 2016 at 00:51:34 UTC, Anon wrote:
 What would you all say to the following proposal (and should I 
 make a DIP?)


 1. deprecate pragma(mangle)
 2. deprecate extern(C++, ns)
 3. deprecate  selector()
 4. Introduce a better, more general extern() as follows:

 extern ( <LanguageIdent> [, <String> ] )
 ...
I was going to propose an additional syntax `extern(C++, "string")` (that doesn't introduce a scope) as a compromise, but your suggestion to extend it to all kinds of foreign languages is even better. I haven't read your proposal in detail, but I definitely like the general idea.
Jan 22
prev sibling parent David Nadlinger <code klickverbot.at> writes:
On Wednesday, 20 January 2016 at 23:21:49 UTC, Walter Bright 
wrote:
 On 1/20/2016 3:12 PM, Martin Drašar via Digitalmars-d wrote:
 The "serious" problem is
 that the decision to have a namespace introduce a new scope 
 needlessly
 complicates writing D-like interfaces to C++ code, while 
 catering for
 one specific use-case that is considered niche.
Adding a qualifier here and there does not count as serious.
But, to put this statement in the context of my other post, it further raises the bar which the arguments in favor of having extern(C++) introduce D-side scopes have to clear. If we had extern(C++, "ns") just affect the mangling, the need for adding extra qualifiers wouldn't exist in the first place. — David
Jan 20
prev sibling parent Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 21 January 2016 at 08:01, Walter Bright via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 1/20/2016 1:47 PM, Timon Gehr wrote:
 On 01/20/2016 09:56 PM, Walter Bright wrote:
 On 1/20/2016 4:17 AM, Manu via Digitalmars-d wrote:
 -- name.x.d--------------------
 module name.x;
 -- name.y.d--------------------
 module name.y;
 import name.x;
 extern(C++, name) int x;
 ------------------------------------
This won't work ...
The suggestion was to just not introduce a new symbol/scope for the namespace. It would certainly work.
I understand his suggestion. I asked Manu to elaborate what the "serious problems" are. This code snippet doesn't work as it is not supposed to work, but still unknown is what the "serious problem" with it is - and I want to ensure that Manu knows this is not a bug in the implementation.
I know it's not a bug in the implementation, it's a bug in the DESIGN. I ****don't want the namespace scope****. My problem and every other problem except the interface inheritance one, is instantly solved. I consider this inability to opt-out when confronted with this set of problems I've shown to be a 'serious' usability problem. Surely the existence of this thread demonstrates that... you understand that if the namespace scope never existed, this entire thread and every problem that I've had would have never existed?
Jan 20
prev sibling next sibling parent Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 21 January 2016 at 06:56, Walter Bright via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 1/20/2016 4:17 AM, Manu via Digitalmars-d wrote:
 -- name.x.d--------------------
 module name.x;
 -- name.y.d--------------------
 module name.y;
 import name.x;
 extern(C++, name) int x;
 ------------------------------------
This won't work any more than: import name.y; struct name { } would. You can't have two different definitions for the same identifier in the same scope, and that's true for any programming language I've heard of.
Of course. But I don't know how you keep missing my point; I didn't declare something called 'name', I declared something called 'x'. I don't want this namespace called 'name'; I didn't declare it, and it causes problems, like this. The obvious response is "well don't declare it then", but that's not an option we're allowed. I want to opt-out of the namespace. I'd prefer the default was to opt-in though.
 ------------------------------------
 extern(C++, delegate) int x;
 ------------------------------------
Yes, we've talked about that. I'm thinking of a solution where it could be written like: extern(C++, delegate_) int x; and the C++ name mangler strips off any trailing _.
It's a solution I guess... I wouldn't call it intuitive. Why would someone reading the code expect that behaviour? But again, it's completely unnecessary. I don't want a namespace called 'delegate'. I don't want to declare any D identifier anywhere called 'delegate', I just want it to mangle 'x' properly. You're proposing a work-around to a problem that shouldn't exist in the first place. The proper solution is to make the problem not exist.
 Note that this problem is NOT resolved by your proposed solution, as this
 wouldn't work, either:

    extern(C++) int* delegate();
 You claim this is a problem that must desperately be solved:
 ------------------------------------
 int x;
 extern(C++, ns) int x;
 ------------------------------------

 The solution arrives at basically the same problem:
 ------------------------------------
 int ns;
 extern(C++, ns) int x;
 ------------------------------------

 We've just robbed peter to pay paul?
C++ doesn't allow: int ns; namespace ns { ... } either, so there can never be a need to solve that problem.
I'm declaring 'x', not 'ns'. using the namespace to resolve conflict in the first case just creates a second potential for conflict. It's kicked the can, and hasn't reliably solved the problem. Name conflict resolution and name mangling are separate issues, it's no good to conflate them. I'd rather resolve the conflict in a normal D way like any normal D user would. I can best choose how to resolve the conflict with consideration for the case, and this issue has nothing to do with name mangling.
 scanning reflection
 needs to be retrofit with new tricks to recurse into namespaces:
 ------------------------------------
 extern(C++, ns) void f();
 pragma(msg, __traits(allMembers, mixin(__MODULE__)));
 ------------------------------------
 tuple("object", "ns")
... f() is not present. By extension of this, extern(C++, ns) declarations are incompatible with every single implementation of scanning reflection I've written in the past 6 years, and everyone else's too. All such code needs to be retrofit with new tricks to recurse into ns.
Seems to me that all that is necessary is to replace: __traits(allMembers, mixin(__MODULE__)) with: getAllMembersIncludingNs(mixin(__MODULE__)) and then write getAllMembersIncludingNS() as a function that recursively adds members of namespaces. After all, the ugly __traits() was always meant to be a building block to be encapsulated by a function that does what is really wanted. I wouldn't call it tricky.
">> All such code needs to be retrofit with new tricks to recurse into ns." I understand I can correct the situation by changing the code, but there is an awful lot of reflection code that already exists, mostly in libraries. Normal programmers don't tend to change library code, they just assume that it doesn't work. You guys hate breaking code, I'm surprised you're not more upset by this. I'm frustrated by the other cases, because you're making me to do work and waste time here complaining about a problem that simply shouldn't exist in the first place. This is the one that really upsets me though. I don't want the namespace to exist. I just want extern(C++, "ns") to take a string, not make a scope, every single problem is solved, and you'll not hear from me for another 6 months.
Jan 20
prev sibling parent tsbockman <thomas.bockman gmail.com> writes:
On Wednesday, 20 January 2016 at 20:56:49 UTC, Walter Bright 
wrote:
 On 1/20/2016 4:17 AM, Manu via Digitalmars-d wrote:
 You claim this is a problem that must desperately be solved:
 ------------------------------------
 int x;
 extern(C++, ns) int x;
 ------------------------------------

 The solution arrives at basically the same problem:
 ------------------------------------
 int ns;
 extern(C++, ns) int x;
 ------------------------------------

 We've just robbed peter to pay paul?
C++ doesn't allow: int ns; namespace ns { ... } either, so there can never be a need to solve that problem.
In Manu's example, `int ns` is a native D variable, not an extern(C++) one. The C++ code you responded with has no relevance to whether Manu's example could or should work; it's entirely determined by the design of the D compiler. More generally, the basic purpose of `extern(C++)` is simply to indicate that a D identifier should be mapped to a certain C++ symbol. It makes no sense to insist that the D identifier *must* be derived from the C++ symbol in a some specific way (that is, by including the C++ namespace in the D identifier) to make the problem tractable. If you wanted to, you could easily make the mapping totally arbitrary with something like `pragma(mangle)`. Given that the mapping could be anything you choose, how can D's identifier disambiguation facilities be adequate for native D symbols, and yet not for C++ symbols? Why must there be any difference between the two at all?
Jan 20
prev sibling parent reply David Nadlinger <code klickverbot.at> writes:
On Tuesday, 19 January 2016 at 22:14:42 UTC, Walter Bright wrote:
 1. C++ has namespaces. They went and invented a whole 'nother 
 thing called modules. Evidently not even they think that 
 modules and namespaces are the same thing.
C++ modules (as per N4465, etc.) are a whole different story and entirely unrelated to the discussion. Their existence is neither an argument for or against having extern(C++) create named scopes for namespaces.
 2. Multiple modules cannot have the same name in D. C++ 
 practice is to litter code with namespaces using the same name.
If you want to split up the interface to a C++ namespace among different modules, then the different symbols will *always* reside in different fully qualified scopes – with or without additional scopes being introduced by extern(C++)! The fact that modules are "sealed" scopes is an integral part of the D module system, and while your statement is true, I'm not sure how it constitutes an argument for having extern(C++) introduce more scopes in addition to that.
 3. Modules have ModuleInfos, static constructors/destructors, 
 etc. These do not make obvious sense for namespaces.
How does this apply to the discussion? Again, extern(C++) code lives inside a D module either way.
 […]
Actually, I'll skip commenting on the other points for now, because reading your last paragraph makes me suspect that there is a misunderstanding:
 I.e. if modules were bludgeoned into being namespaces, there 
 would be such a list of special cases and confusions and 
 exceptions and awkward crap you'd be far, far better off having 
 namespace as a SEPARATE feature, because that's what they'd 
 wind up being anyway, even if they were named "modules".
From this statement, it seems as if you think we are arguing for modules somehow being mapped directly to C++ namespaces, in the vein of some hypothetical "module(C++, ns) foo;" declaration. However, this is not the case at all. Quite the contrary, my proposal (and, as far as I understand also that of Manu, Daniel and others who have agued against your design) is that C++ namespaces should have no semantic representation on the D side at all. We like our D modules as they are [1], and we are certainly not trying to bludgeon them into any other shape. Given the vast semantical differences between them and C++ namespaces – and you haven't even really mentioned the extensibility aspect and the new inline namespaces in your list – this would be a foolish thing to do. Modules only enter the picture in so far as they provide a natural way for client code of two C++ library wrappers to disambiguate between two symbols that have the same name, as it might happen if they correspond to C++ symbols from different namespaces. In other words, modules would likely quite often happen to provide the necessary means of disambiguation, because one would put the wrappers for two different C++ namespaces into different D modules anyway. But if you wanted to have, say, two declarations for interfacing with both A::foo() and B::foo() within the same D module, you could always use another of D's scoping mechanism for that, like (mixin) templates or whatever else tickles your fancy [2]. — David [1] That is, except for issue 314 and the visibility vs. accessibility problem. [2] Those scopes might of course currently leak into the C++ mangled name – I didn't check –, but this can be fixed.
Jan 20
parent reply Carl Sturtivant <sturtivant gmail.com> writes:
On Thursday, 21 January 2016 at 00:43:13 UTC, David Nadlinger 
wrote:
 If you want to split up the interface to a C++ namespace among 
 different modules, then the different symbols will *always* 
 reside in different fully qualified scopes – with or without 
 additional scopes being introduced by extern(C++)!
This is the nub of the problem, and it's been stated by several people in several different ways in this thread. It means that a C++ namespace which is a single scope, is mapped into one scope per module in D. The C++ namespace scope has been fragmented to make it consistent with D's module philosophy. The result is natural neither for C++ nor for D.
Jan 30
parent Carl Sturtivant <sturtivant gmail.com> writes:
On Sunday, 31 January 2016 at 01:12:11 UTC, Carl Sturtivant wrote:
 This is the nub of the problem, and it's been stated by several 
 people in several different ways in this thread.

 It means that a C++ namespace which is a single scope, is 
 mapped into one scope per module in D. The C++ namespace scope 
 has been fragmented to make it consistent with D's module 
 philosophy. The result is natural neither for C++ nor for D.
In fact, if you're going to bring in a scope to represent a namespace, that's what it needs to be a (singular) scope. Not to bring in many identical but distinct scopes. The present design is falling between two stools. They are to do the above or to just link mangled according to the namespace with no scope special C++ derived scope(s).
Jan 30
prev sibling parent reply David Nadlinger <code klickverbot.at> writes:
On Tuesday, 19 January 2016 at 21:40:01 UTC, Walter Bright wrote:
 Please do not conflate not agreeing with my answers with not 
 responding.
I am not claiming that you weren't participating in the discussion threads or something like that. But in all your arguments you seem to presume that (badly) imitating the scoping semantics of C++ namespaces in D is somehow a given, that it is natural and does not need justification. However, my position is (Manu and Daniel would probably agree) that this is not a valid assumption. To add a new feature to the language, the onus is on you to provide compelling evidence why it is necessary to have. You need to show that there is a "serious problem" with just using the native D namespacing scheme (modules) for the purpose, not the other way round. — David
Jan 20
parent reply Jacob Carlborg <doob me.com> writes:
On 2016-01-21 00:50, David Nadlinger wrote:

 To add a new feature to the language, the
 onus is on you to provide compelling evidence why it is necessary to
 have. You need to show that there is a "serious problem" with just using
 the native D namespacing scheme (modules) for the purpose, not the other
 way round.
Unfortunately that's not how it works with D. If Andrei or Walter have a proposal it's up to the community to provide compelling evidence why it _should not_ be added. If the community has a proposal it's up to the community to provide compelling evidence why is _should_ be added. -- /Jacob Carlborg
Jan 22
next sibling parent Danni Coy via Digitalmars-d <digitalmars-d puremagic.com> writes:
D generally doesn't allow shadowing of names inside inner scopes.

int x;
for (int i=0; i<max; i++) { int x = i*2-1; }

works in a lot of languages but not D.

int x;
extern (C) int x;

doesn't work.

having

int x;
extern (C++,ns) int x;

work
might be useful but to me seems inconsistent with the rest of D.

Using sub modules to deal with this seems very much more consistent
with the rest of the design of D.



On Sat, Jan 23, 2016 at 3:04 AM, Jacob Carlborg via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 2016-01-21 00:50, David Nadlinger wrote:

 To add a new feature to the language, the
 onus is on you to provide compelling evidence why it is necessary to
 have. You need to show that there is a "serious problem" with just using
 the native D namespacing scheme (modules) for the purpose, not the other
 way round.
Unfortunately that's not how it works with D. If Andrei or Walter have a proposal it's up to the community to provide compelling evidence why it _should not_ be added. If the community has a proposal it's up to the community to provide compelling evidence why is _should_ be added. -- /Jacob Carlborg
Jan 25
prev sibling parent David Nadlinger <code klickverbot.at> writes:
On Friday, 22 January 2016 at 17:04:00 UTC, Jacob Carlborg wrote:
 Unfortunately that's not how it works with D. If Andrei or 
 Walter have a proposal it's up to the community to provide 
 compelling evidence why it _should not_ be added. If the 
 community has a proposal it's up to the community to provide 
 compelling evidence why is _should_ be added.
Just to make sure there are no misunderstandings: This is not at all the point I was trying to make. My arguments apply just as well to just a single person deliberating the design: Adding a new feature requires justification, especially if the language is quite large already. Not adding one does not to the same extent, because it is the natural, less risky choice. — David
Jan 30
prev sibling parent reply deadalnix <deadalnix gmail.com> writes:
On Tuesday, 19 January 2016 at 20:29:42 UTC, David Nadlinger 
wrote:
 While I am not in the mood for mudslinging or making a heated 
 discussion out of this, I have to agree with Daniel and Manu 
 here. If I remember correctly, you never really provided any 
 justification (including during the original discussion back 
 when the feature was introduced) as to why just using the 
 normal means of name resolution and disambiguation in D – the 
 module system – is not good enough for this.

 It's fine if you just say "I had a hunch that the added 
 complexity would be worth it by making some situations more 
 convenient, even though I can't provide a concrete example". Of 
 course that might not be particularly persuasive, but it's your 
 call in the end. But if you keep dodging the question, this 
 discussion will never come to an end.

  — David
Isn't the fact that this is what they do in C++ good enough ? I mean, if it wasn't a desirable feature, the C++ code writer would probably not have used it.
Jan 19
parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 20 January 2016 at 10:49, deadalnix via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Tuesday, 19 January 2016 at 20:29:42 UTC, David Nadlinger wrote:
 While I am not in the mood for mudslinging or making a heated discussion
 out of this, I have to agree with Daniel and Manu here. If I remember
 correctly, you never really provided any justification (including during the
 original discussion back when the feature was introduced) as to why just
 using the normal means of name resolution and disambiguation in D – the
 module system – is not good enough for this.

 It's fine if you just say "I had a hunch that the added complexity would
 be worth it by making some situations more convenient, even though I can't
 provide a concrete example". Of course that might not be particularly
 persuasive, but it's your call in the end. But if you keep dodging the
 question, this discussion will never come to an end.

  — David
Isn't the fact that this is what they do in C++ good enough ? I mean, if it wasn't a desirable feature, the C++ code writer would probably not have used it.
The C++ namespace semantic doesn't have a proper analogy in D, and the D code is already organised into modules anyway making mirroring of the C++ semantic irrelevant. We don't mirror C/C++ semantics in other facets of the bindings, we just make it link. There's no reason to deviate from that pattern here. Nobody seems to want to address the problem points I raise in my last email though. If it was benign, I wouldn't care, but it causes way more harm than good.
Jan 19
parent reply deadalnix <deadalnix gmail.com> writes:
On Wednesday, 20 January 2016 at 02:15:27 UTC, Manu wrote:
 The C++ namespace semantic doesn't have a proper analogy in D, 
 and the
 D code is already organised into modules anyway making 
 mirroring of
 the C++ semantic irrelevant.
 We don't mirror C/C++ semantics in other facets of the 
 bindings, we
 just make it link. There's no reason to deviate from that 
 pattern
 here.
 Nobody seems to want to address the problem points I raise in 
 my last
 email though. If it was benign, I wouldn't care, but it causes 
 way
 more harm than good.
What happens when one has conflicting symbols in 2 C++ namespaces ? D's mapping of C++ namespaces could just mimic how import resolution work : allow qualified and unqualified access to the symbol when there is no conflict, forces you to use the qualified one when there (or to create an alias, or whatever).
Jan 19
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 01/20/2016 03:25 AM, deadalnix wrote:
 On Wednesday, 20 January 2016 at 02:15:27 UTC, Manu wrote:
 The C++ namespace semantic doesn't have a proper analogy in D, and the
 D code is already organised into modules anyway making mirroring of
 the C++ semantic irrelevant.
 We don't mirror C/C++ semantics in other facets of the bindings, we
 just make it link. There's no reason to deviate from that pattern
 here.
 Nobody seems to want to address the problem points I raise in my last
 email though. If it was benign, I wouldn't care, but it causes way
 more harm than good.
What happens when one has conflicting symbols in 2 C++ namespaces ? D's mapping of C++ namespaces could just mimic how import resolution work : allow qualified and unqualified access to the symbol when there is no conflict, forces you to use the qualified one when there (or to create an alias, or whatever).
That's how it works. However, two namespace declarations with the same identifier will conflict, unlike in C++.
Jan 19
next sibling parent deadalnix <deadalnix gmail.com> writes:
On Wednesday, 20 January 2016 at 02:51:55 UTC, Timon Gehr wrote:
 What happens when one has conflicting symbols in 2 C++ 
 namespaces ?

 D's mapping of C++ namespaces could just mimic how import 
 resolution
 work : allow qualified and unqualified access to the symbol 
 when there
 is no conflict, forces you to use the qualified one when there 
 (or to
 create an alias, or whatever).
That's how it works. However, two namespace declarations with the same identifier will conflict, unlike in C++.
Well that can - and should - fixed fairly easily.
Jan 19
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/19/2016 6:51 PM, Timon Gehr wrote:
 That's how it works. However, two namespace declarations with the same
 identifier will conflict, unlike in C++.
Right. Also, in C++, function overloading can behave erratically depending on which version(s) of a namespace are visible or not. D doesn't have this problem, you'll have to use aliases and/or qualification if overloading across namespaces with the same name. (The usual anti-hijacking rules.)
Jan 19
parent Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 20 January 2016 at 13:20, Walter Bright via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 1/19/2016 6:51 PM, Timon Gehr wrote:
 That's how it works. However, two namespace declarations with the same
 identifier will conflict, unlike in C++.
Right. Also, in C++, function overloading can behave erratically depending on which version(s) of a namespace are visible or not. D doesn't have this problem, you'll have to use aliases and/or qualification if overloading across namespaces with the same name. (The usual anti-hijacking rules.)
This is no different than normal use of modules.
Jan 19
prev sibling parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 20 January 2016 at 12:25, deadalnix via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Wednesday, 20 January 2016 at 02:15:27 UTC, Manu wrote:
 The C++ namespace semantic doesn't have a proper analogy in D, and the
 D code is already organised into modules anyway making mirroring of
 the C++ semantic irrelevant.
 We don't mirror C/C++ semantics in other facets of the bindings, we
 just make it link. There's no reason to deviate from that pattern
 here.
 Nobody seems to want to address the problem points I raise in my last
 email though. If it was benign, I wouldn't care, but it causes way
 more harm than good.
What happens when one has conflicting symbols in 2 C++ namespaces ?
Put them in different modules. Can you actually imagine a case in C++ where 2 symbols with the same name are declared next to eachother under different namespaces in the same place, such that they wouldn't be naturally divided into separate modules in the first place? This case appears to be the soul purpose of the design, and I'm trying to convince that this is truly a very niche case, whereas the situation we are in presents problems in the common case. Workarounds should be required for the niche cases, not the common case.
 D's mapping of C++ namespaces could just mimic how import resolution work :
 allow qualified and unqualified access to the symbol when there is no
 conflict, forces you to use the qualified one when there (or to create an
 alias, or whatever).
It does work that way, and it's fine; it's no difference from if the namespace weren't there at all... until you DO need to disambiguate for some reason; the proposed point is to use ns.symbol, but you can't in practise because ns is always in conflict with some other module, so you have to use my.lib.ns.symbol. As soon as you must justify the full name including the module, the namespace has failed at it's one job. It may as well not be present. That in itself is not a serious problems though, but the presence of the namespaces do present other serious problems which are completely unnecessary symptoms of the design, especially when you consider it actually fails as it's only purpose in practise. I mentioned problems in my prior post, and repeatedly before that, and nobody has addressed any of them yet.
Jan 19
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/19/2016 7:54 PM, Manu via Digitalmars-d wrote:
 That in itself is not a serious problems though, but the presence of
 the namespaces do present other serious problems which are completely
 unnecessary symptoms of the design, especially when you consider it
 actually fails as it's only purpose in practise.
 I mentioned problems in my prior post, and repeatedly before that, and
 nobody has addressed any of them yet.
Actual code examples of the serious problems would be appreciated. All the namespace code examples you posted were bugs that have since been fixed, or were misunderstandings that were explained.
Jan 19
next sibling parent Danni Coy via Digitalmars-d <digitalmars-d puremagic.com> writes:
I have been turning this over in my head for the last week.

What about something along the lines of
extern (C++,module)
{
}
which keeps code at the module level on the D side and puts code into
a namespace that mirrors the D module name.


On Wed, Jan 20, 2016 at 3:32 PM, Walter Bright via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 1/19/2016 7:54 PM, Manu via Digitalmars-d wrote:
 That in itself is not a serious problems though, but the presence of
 the namespaces do present other serious problems which are completely
 unnecessary symptoms of the design, especially when you consider it
 actually fails as it's only purpose in practise.
 I mentioned problems in my prior post, and repeatedly before that, and
 nobody has addressed any of them yet.
Actual code examples of the serious problems would be appreciated. All the namespace code examples you posted were bugs that have since been fixed, or were misunderstandings that were explained.
Jan 19
prev sibling parent reply Marc =?UTF-8?B?U2Now7x0eg==?= <schuetzm gmx.net> writes:
On Wednesday, 20 January 2016 at 05:32:08 UTC, Walter Bright 
wrote:
 Actual code examples of the serious problems would be 
 appreciated. All the namespace code examples you posted were 
 bugs that have since been fixed, or were misunderstandings that 
 were explained.
IMO his description was already quite clear, but here you are: // a.d module a; extern(C++, ns) { void fooa(); void bar(); } // b.d module b; extern(C++, ns) { void foob(); } void bar(); // main.d import a, b; void main() { fooa(); // ok foob(); // ok bar(); // Error: b.bar at b.d(6) conflicts with a.ns.bar at a.d(5) // let's try to disambiguate: we want ns.bar ns.bar(); // Error: a.ns at a.d(3) conflicts with b.ns at b.d(3) a.ns.bar(); // works, but requires superfluous `a`, even though // `ns` already makes it unambiguous } Of course, it's because of how name lookup works in D, and we understand that. But it still diminishes the usability of this feature considerably, as the above situation is extremely likely to run into if you're porting a sufficiently large C++ library.
Jan 20
next sibling parent reply JohnCK <j j.com> writes:
On Wednesday, 20 January 2016 at 16:38:19 UTC, Marc Schütz wrote:
 // a.d
 module a;

 extern(C++, ns) {
     void fooa();
     void bar();
 }

 // b.d
 module b;

 extern(C++, ns) {
     void foob();
 }
 void bar();

 // main.d
 import a, b;

 void main() {
     fooa();     // ok
     foob();     // ok
     bar();      // Error: b.bar at b.d(6) conflicts with 
 a.ns.bar at a.d(5)
     // let's try to disambiguate: we want ns.bar
     ns.bar();   // Error: a.ns at a.d(3) conflicts with b.ns at 
 b.d(3)
     a.ns.bar(); // works, but requires superfluous `a`, even 
 though
                 // `ns` already makes it unambiguous
 }
I think the first error is correct:
     bar();      // Error: b.bar at b.d(6) conflicts with 
 a.ns.bar at a.d(5)
So you have two functions bar() one inside 'ns' in module a and "outside" 'ns' in module b. Now, the last 2 errors, Mark Schutz said:
     a.ns.bar(); // works, but requires superfluous `a`, even 
 though
                 // `ns` already makes it unambiguous
Question: What happens if you do this: using "ns1" in "module a" and "ns2" in "module b" and do: ns1.bar(); ? Because you can't have more than one namespaces with the same name in C++, right? JohnCK.
Jan 20
parent Marc =?UTF-8?B?U2Now7x0eg==?= <schuetzm gmx.net> writes:
On Wednesday, 20 January 2016 at 17:25:56 UTC, JohnCK wrote:
 On Wednesday, 20 January 2016 at 16:38:19 UTC, Marc Schütz 
 wrote:
 I think the first error is correct:

     bar();      // Error: b.bar at b.d(6) conflicts with 
 a.ns.bar at a.d(5)
Yes, I put this one in to show why the next lines are sometimes necessary.
 So you have two functions bar() one inside 'ns' in module a and 
 "outside" 'ns' in module b.

 Now, the last 2 errors, Mark Schutz said:

     a.ns.bar(); // works, but requires superfluous `a`, even 
 though
                 // `ns` already makes it unambiguous
Question: What happens if you do this: using "ns1" in "module a" and "ns2" in "module b" and do: ns1.bar(); ?
There'd be no collision anymore, but...
 Because you can't have more than one namespaces with the same 
 name in C++, right?
You can: namespace ns { void foo(); } namespace ns { void bar(); } int main() { ns::bar(); return 0; } More realistically, the namespace declarations would appear in different header files, all #included into the same cpp file. These different header files would naturally be mapped to different D modules.
Jan 20
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/20/2016 8:38 AM, Marc Schütz wrote:
 IMO his description was already quite clear, but here you are:
What's missing is why this is a *serious* problem. All you've got to do is add a qualifier.
Jan 20
next sibling parent Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 21 January 2016 at 08:15, Walter Bright via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 1/20/2016 8:38 AM, Marc Schütz wrote:
 IMO his description was already quite clear, but here you are:
What's missing is why this is a *serious* problem. All you've got to do is add a qualifier.
It's 'serious' in that my cases are very highly likely; almost guaranteed to occur, indeed they occurred within minutes of my test-driving this feature. The design has a very high probability of inhibiting usability, and I can't imagine a real-world situation where it improves usability. I've tried to demonstrate some practical and very likely occurring cases which show that the design isn't correct; I have hit all of them. I just want to opt-out. I don't want to hear about workarounds... I don't want to explain the various workarounds to other people when they encounter these problems that there's no reason for them to encounter in the first place. I don't want name conflict resolution to behave in a special way because the .lib file happened to be compiled by a C++ compiler. I just want to tell the name mangler the C++ namespace, and let me get back to writing D code. Every single problem I've had with extern(C++, ns), and continue to have, is solved by not emitting a namespace scope, and I can't imagine a case where it will help me. Seriously, I'm not exaggerating here. The design does not carry its weight.
Jan 20
prev sibling parent Daniel Murphy <yebbliesnospam gmail.com> writes:
On 21/01/2016 9:15 AM, Walter Bright wrote:
 On 1/20/2016 8:38 AM, Marc Schütz wrote:
 IMO his description was already quite clear, but here you are:
What's missing is why this is a *serious* problem. All you've got to do is add a qualifier.
The *serious* problem is that the added scope does not appear to add practical value, yet has a non-zero cost. And yes I've seen your example with two same-named symbols in the same module, but I really don't understand why *that* is a serious problem that the namespace scope is worth introducing to solve. And I am not personally arguing for D modules mapping to C++ namespaces - the alternative feature I have in mind is extern(C++, "namespace") affecting mangling and *nothing else*.
Jan 21
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 1/19/2016 5:56 AM, Manu via Digitalmars-d wrote:
 It looks like you understand there's no objective justification for
 the design. I suspect you just don't want to change it now it's in.
The number of my replies suggests otherwise. You don't agree with what I say, ok, but that doesn't mean I did not reply or otherwise engage with you, nor does it mean I am secretly convinced by your arguments.
Jan 19
prev sibling parent reply Chris Wright <dhasenan gmail.com> writes:
On Sun, 17 Jan 2016 22:55:23 +1100, Daniel Murphy wrote:

 So now we have two public symbols called 'mylib', and because they
 conflict they can't be used to disambiguate eg 'someotherlib.funca' with
 'library.a.funca'.
Users want to disambiguate between a use of C++ namespace members and other values from other modules. The natural way to do this is to provide a fully qualified D name. For instance, if I wrapped C++ type Urho3D::Core::Context in D module urho3d.core, I'd normally refer to it as urho3d.core.Context. That works today. It's got no problems. However, in your scenario, users don't want to use the D module names to disambiguate. They want to use C++ namespaces. Why?
Jan 17
parent Daniel Murphy <yebbliesnospam gmail.com> writes:
On 18/01/2016 12:19 PM, Chris Wright wrote:
 On Sun, 17 Jan 2016 22:55:23 +1100, Daniel Murphy wrote:

 So now we have two public symbols called 'mylib', and because they
 conflict they can't be used to disambiguate eg 'someotherlib.funca' with
 'library.a.funca'.
Users want to disambiguate between a use of C++ namespace members and other values from other modules. The natural way to do this is to provide a fully qualified D name. For instance, if I wrapped C++ type Urho3D::Core::Context in D module urho3d.core, I'd normally refer to it as urho3d.core.Context. That works today. It's got no problems. However, in your scenario, users don't want to use the D module names to disambiguate. They want to use C++ namespaces. Why?
IMO the only reason to use C++ namespaces in D is to match mangling of a C++ library you want to link to. If they just changed mangling and nothing else, then they would do their job just fine.
Jan 19
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 01/12/2016 11:46 PM, Manu via Digitalmars-d wrote:
 I understand, and I've said I'll find the time to reduce my case and
 we can do that work. I just don't have any free time at work right
 now, I'll get to this as soon as I can.
This will work exceedingly well. Thanks.
 Regarding this discussion, as far as I'm concerned, this is a separate
 conversation regarding the validity of the features existence. I want
 to convince you that it's wrong. Fixing the existing design is a
 separate conversation, which I'll reopen as soon as I have more
 information for you.
 Of course, it would save a lot of effort if you agreed that the design
 is wrong, and none of us need to do anything further.
This is less likely to go over well. Walter and I pore over your posts over the phone and are unable to understand what you mean to say, down to the use of vocabulary (e.g. "lookup" when no lookup is involved). Often we have no idea what "this" or "it" refers to in text. It is clear there is a problem somewhere. The best way, by far, to make progress is to show code that should work and doesn't. Andrei
Jan 13
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 1/11/2016 12:45 AM, Rainer Schuetze wrote:
 It gets worse if you add D's std package into the mix by adding the commented
 lines:
Andrei and I plan to place the C++ STL interface into the package core.stdcpp (alongside existing core.stdc), which will avoid name conflicts with Phobos' std.
Jan 11
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/7/2016 9:14 PM, Manu via Digitalmars-d wrote:
 The namespace offers nothing, and introduces problems. We don't want it.
The problems you were having were due to two bugs, since corrected, and one misunderstanding on how name lookups were done. I went through all your examples in the bugzilla issues you reported. All work now, except the one that was based on a misunderstanding and was not a bug. I'd recommend trying it out with the fixes, and then if there are further problems, post a list of examples. (I'm aware of the remaining issue with a C++ namespace named 'delegate'.)
Jan 08
parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 8 January 2016 at 23:40, Walter Bright via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 1/7/2016 9:14 PM, Manu via Digitalmars-d wrote:
 The namespace offers nothing, and introduces problems. We don't want it.
The problems you were having were due to two bugs, since corrected, and one misunderstanding on how name lookups were done.
Nope. I've tried the latest nightly against my code. I can confirm the forward-referencing issues seem to be gone, but I had already worked very hard to arrange and order my code to avoid that issue, so that wasn't actually my problem (as I suspected). This patch allows me to un-obfuscate my code by putting it back in readable order, but the rest of my issues seem to be un-changed. They are all name-in-namespace resolution related. As a quick test, I changed extern(C++, ns), to extern(C++) in the files where it couldn't find anything, and all the symbols became visible and everything worked as it should (except obviously I couldn't link). Sadly, I don't have any more time I can allocate to this, I'll have to chip away at it any further after hours. I really hoped I could get this working over Christmas. I'll continue to try and reduce the structure of the problem, but I still just wish you'd remove the namespace scope. Everything would be fixed instantly, I am certain of this. This design doesn't give us anything, and you seem to be resisting making an argument for its existence. We don't need to do this, we don't need to waste any more time.
Jan 10
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/10/2016 5:20 PM, Manu via Digitalmars-d wrote:
 This design doesn't give us anything, and you seem to be resisting
 making an argument for its existence. We don't need to do this, we
 don't need to waste any more time.
I appreciate that, but without knowing exactly what your issue is, I can't draw any sort of conclusion.
Jan 10
next sibling parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 11 January 2016 at 11:59, Walter Bright via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 1/10/2016 5:20 PM, Manu via Digitalmars-d wrote:
 This design doesn't give us anything, and you seem to be resisting
 making an argument for its existence. We don't need to do this, we
 don't need to waste any more time.
I appreciate that, but without knowing exactly what your issue is, I can't draw any sort of conclusion.
I can't say without spending a whole bunch of time trying to work it out. What I can consistently show is that when I substitute 'extern(C++, ns)' for 'extern(C++)', all problems vanish (subsequent link errors aside). It would seem that name resolution is more complex than normal, and it gets complicated or breaks in edge cases. Then I need to spend time trying to understand how it is that my case is complex, and trying to workaround it (or produce sufficient examples). But the whole dance is pointless. If we could just recognise that the ns scope only increases complexity, there's no good reason for it, and there's no opt out. Just let the symbols be exactly where they're declared like any regular D code, and if you really want this namespace scoping feature, can we take that as a separate enhancement request and discuss/design it? I'd suggest it should be opt-in, since I can't imagine a case where I would ever want that behaviour.
Jan 10
parent Walter Bright <newshound2 digitalmars.com> writes:
On 1/10/2016 6:54 PM, Manu via Digitalmars-d wrote:
 It would seem that name resolution is more complex than normal, and it
 gets complicated or breaks in edge cases. Then I need to spend time
 trying to understand how it is that my case is complex, and trying to
 workaround it (or produce sufficient examples).
 But the whole dance is pointless. If we could just recognise that the
 ns scope only increases complexity, there's no good reason for it, and
 there's no opt out.
 Just let the symbols be exactly where they're declared like any
 regular D code, and if you really want this namespace scoping feature,
 can we take that as a separate enhancement request and discuss/design
 it? I'd suggest it should be opt-in, since I can't imagine a case
 where I would ever want that behaviour.
I'd like to distinguish what's going wrong: 1. a bug in the implementation 2. a bug in the design 3. a bug in your mental model of how it works 4. unawareness of a feature in D designed for the situation before throwing it all away and rebooting the design. Note that I have been able to help you when you've got an example illustrating the issue you're having.
Jan 10
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 01/11/2016 02:59 AM, Walter Bright wrote:
 On 1/10/2016 5:20 PM, Manu via Digitalmars-d wrote:
 This design doesn't give us anything, and you seem to be resisting
 making an argument for its existence. We don't need to do this, we
 don't need to waste any more time.
I appreciate that, but without knowing exactly what your issue is, I can't draw any sort of conclusion.
Actually you can. If replacing extern(C++,ns) with extern(C++) fixes undefined identifier errors, then we are talking about a bug in the implementation.
Jan 11
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/11/2016 12:23 PM, Timon Gehr wrote:
 If replacing extern(C++,ns) with extern(C++) fixes undefined
 identifier errors, then we are talking about a bug in the implementation.
No: ----- module s; int ns,b; ----- module t; int ns,c; ----- import s; import t; void foo() { int x = ns; // Error: 's.ns' or 't.ns'? b = c; // no problem } ----- Why do the same name lookup rules become a bug if "int ns" is replaced with "extern(C++,ns)" ?
Jan 11
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 01/11/2016 09:53 PM, Walter Bright wrote:
 On 1/11/2016 12:23 PM, Timon Gehr wrote:
 If replacing extern(C++,ns) with extern(C++) fixes undefined
 identifier errors, then we are talking about a bug in the implementation.
No: ----- module s; int ns,b; ----- module t; int ns,c; ----- import s; import t; void foo() { int x = ns; // Error: 's.ns' or 't.ns'?
This not an undefined identifier error.
     b = c;       // no problem
 }
 -----

 Why do the same name lookup rules become a bug if "int ns" is replaced
 with "extern(C++,ns)" ?
They don't.
Jan 11
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/11/2016 12:56 PM, Timon Gehr wrote:
 This not an undefined identifier error.
Please post an example of the bug you assert.
Jan 11
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 01/11/2016 10:12 PM, Walter Bright wrote:
 On 1/11/2016 12:56 PM, Timon Gehr wrote:
 This not an undefined identifier error.
Please post an example of the bug you assert.
I can't, as Manu hasn't provided the code. I'm just saying that, if the following is true: On 01/11/2016 02:20 AM, Manu via Digitalmars-d wrote:
 As a quick test, I changed extern(C++, ns), to extern(C++) in the
 files where it couldn't find anything, and all the symbols became
 visible and everything worked as it should (except obviously I
 couldn't link).
Then this indicates the existence of a compiler bug. I.e. it is not possible that there is no bug related to name lookup in namespaces, as otherwise symbols wouldn't go from invisible to visible by removing the wrapping namespace.
Jan 11
parent Walter Bright <newshound2 digitalmars.com> writes:
On 1/11/2016 4:18 PM, Timon Gehr wrote:
 On 01/11/2016 10:12 PM, Walter Bright wrote:
 On 1/11/2016 12:56 PM, Timon Gehr wrote:
 This not an undefined identifier error.
Please post an example of the bug you assert.
I can't, as Manu hasn't provided the code.
This amply illustrates the futility of proceeding without an actual test case.
Jan 11
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 1/10/16 8:20 PM, Manu via Digitalmars-d wrote:
 I'll continue to try and reduce the structure of the problem, but I
 still just wish you'd remove the namespace scope. Everything would be
 fixed instantly, I am certain of this.
Do you have other examples that should work but don't? Thx! -- Andrei
Jan 10
parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 11 January 2016 at 12:38, Andrei Alexandrescu via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 1/10/16 8:20 PM, Manu via Digitalmars-d wrote:
 I'll continue to try and reduce the structure of the problem, but I
 still just wish you'd remove the namespace scope. Everything would be
 fixed instantly, I am certain of this.
Do you have other examples that should work but don't? Thx! -- Andrei
I only have the code I'm working on. I just don't have free time available to me to work on home/side projects the last 6 months >_< I used some gaps while other staff were on Christmas holidays to make an effort at this, but that time has passed. I'll do another pass over my code as I am able, since bugs have been fixes the situation has changed, and I effectively need to repeat all the experiments I've done.
Jan 10
next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 1/10/2016 7:05 PM, Manu via Digitalmars-d wrote:
 I'll do another pass over my code as I am able, since bugs have been
 fixes the situation has changed, and I effectively need to repeat all
 the experiments I've done.
Thank you. I also suggest that you come here for help sooner so you don't spend so much time beating your head on the wall.
Jan 10
prev sibling next sibling parent Rikki Cattermole <alphaglosined gmail.com> writes:
On 11/01/16 4:05 PM, Manu via Digitalmars-d wrote:
 On 11 January 2016 at 12:38, Andrei Alexandrescu via Digitalmars-d
 <digitalmars-d puremagic.com> wrote:
 On 1/10/16 8:20 PM, Manu via Digitalmars-d wrote:
 I'll continue to try and reduce the structure of the problem, but I
 still just wish you'd remove the namespace scope. Everything would be
 fixed instantly, I am certain of this.
Do you have other examples that should work but don't? Thx! -- Andrei
I only have the code I'm working on. I just don't have free time available to me to work on home/side projects the last 6 months >_< I used some gaps while other staff were on Christmas holidays to make an effort at this, but that time has passed. I'll do another pass over my code as I am able, since bugs have been fixes the situation has changed, and I effectively need to repeat all the experiments I've done.
Would it be possible to send the code to Walter to take a look at and maybe have a go with?
Jan 10
prev sibling parent deadalnix <deadalnix gmail.com> writes:
On Monday, 11 January 2016 at 03:05:44 UTC, Manu wrote:
 On 11 January 2016 at 12:38, Andrei Alexandrescu via 
 Digitalmars-d <digitalmars-d puremagic.com> wrote:
 On 1/10/16 8:20 PM, Manu via Digitalmars-d wrote:
 I'll continue to try and reduce the structure of the problem, 
 but I still just wish you'd remove the namespace scope. 
 Everything would be fixed instantly, I am certain of this.
Do you have other examples that should work but don't? Thx! -- Andrei
I only have the code I'm working on. I just don't have free time available to me to work on home/side projects the last 6 months >_< I used some gaps while other staff were on Christmas holidays to make an effort at this, but that time has passed. I'll do another pass over my code as I am able, since bugs have been fixes the situation has changed, and I effectively need to repeat all the experiments I've done.
Can the code be shared ? Maybe you could use dustmite to reduce the bug to a manageable code size.
Jan 11
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2016-01-11 02:20, Manu via Digitalmars-d wrote:

 Sadly, I don't have any more time I can allocate to this, I'll have to
 chip away at it any further after hours. I really hoped I could get
 this working over Christmas.
 I'll continue to try and reduce the structure of the problem, but I
 still just wish you'd remove the namespace scope. Everything would be
 fixed instantly, I am certain of this.
 This design doesn't give us anything, and you seem to be resisting
 making an argument for its existence. We don't need to do this, we
 don't need to waste any more time.
Would it be possible to make the code available somewhere. Remove the implementations and rename the symbols, or would that be too much work? -- /Jacob Carlborg
Jan 11
next sibling parent Daniel N <ufo orbiting.us> writes:
On Monday, 11 January 2016 at 08:56:40 UTC, Jacob Carlborg wrote:
 On 2016-01-11 02:20, Manu via Digitalmars-d wrote:

 Sadly, I don't have any more time I can allocate to this, I'll 
 have to
 chip away at it any further after hours. I really hoped I 
 could get
 this working over Christmas.
 I'll continue to try and reduce the structure of the problem, 
 but I
 still just wish you'd remove the namespace scope. Everything 
 would be
 fixed instantly, I am certain of this.
 This design doesn't give us anything, and you seem to be 
 resisting
 making an argument for its existence. We don't need to do 
 this, we
 don't need to waste any more time.
Would it be possible to make the code available somewhere. Remove the implementations and rename the symbols, or would that be too much work?
I may have found a workaround... (verified with dmd 2.069.2), works better than alias since everything inside ns can be made private. enum bindings = q{ pragma(mangle, ns.fun.mangleof) extern(C++) void fun(); }; private extern(C++, ns) { private: mixin(bindings); } mixin(bindings);
Jan 11
prev sibling parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 11 January 2016 at 18:56, Jacob Carlborg via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 2016-01-11 02:20, Manu via Digitalmars-d wrote:

 Sadly, I don't have any more time I can allocate to this, I'll have to
 chip away at it any further after hours. I really hoped I could get
 this working over Christmas.
 I'll continue to try and reduce the structure of the problem, but I
 still just wish you'd remove the namespace scope. Everything would be
 fixed instantly, I am certain of this.
 This design doesn't give us anything, and you seem to be resisting
 making an argument for its existence. We don't need to do this, we
 don't need to waste any more time.
Would it be possible to make the code available somewhere. Remove the implementations and rename the symbols, or would that be too much work?
Yeah, I'll get to it as I can. It's just a lot of fiddling and I've already spent all my time on this.
Jan 11
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 01/11/2016 10:00 PM, Manu via Digitalmars-d wrote:
 Yeah, I'll get to it as I can. It's just a lot of fiddling and I've
 already spent all my time on this.
Thanks, Manu. This is awesome stuff. Code that should work but doesn't is the best way to press things forward. -- Andrei
Jan 11
parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 12 January 2016 at 13:17, Andrei Alexandrescu via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 01/11/2016 10:00 PM, Manu via Digitalmars-d wrote:
 Yeah, I'll get to it as I can. It's just a lot of fiddling and I've
 already spent all my time on this.
Thanks, Manu. This is awesome stuff. Code that should work but doesn't is the best way to press things forward. -- Andrei
It's a painful proposition though. Can you see the pointless-ness of this feature and the effort being asked? It is against my interest to spend time (that I don't have) to make this feature work, when I am 100% convinced it is a massive anti-feature and I just want to see it ejected into space. It creates nothing but edges and offers nothing. Not a single advantage that anyone has yet been able present. The solution is simple, and solves every related issue instantly. There's no point wasting time identifying and fixing bugs in an implementation that shouldn't exist in the first place. This never should have happened, we can correct it easily, no effort from anyone is required, and we can all get on with something else. Do you also feel somehow emotionally attached to this? Give me a thread of logic to grasp on to; there is no way I can imagine to objectively balance the existence of this feature against the problems. We already see here demonstrated evidence of someone other than me going out of their way to awkwardly eliminate the namespace from existence. It should at least be opt-in by default. Anyway, I'm out, I'll be back when I find time for another round at this code.
Jan 11
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 01/11/2016 11:29 PM, Manu via Digitalmars-d wrote:
 On 12 January 2016 at 13:17, Andrei Alexandrescu via Digitalmars-d
 <digitalmars-d puremagic.com> wrote:
 On 01/11/2016 10:00 PM, Manu via Digitalmars-d wrote:
 Yeah, I'll get to it as I can. It's just a lot of fiddling and I've
 already spent all my time on this.
Thanks, Manu. This is awesome stuff. Code that should work but doesn't is the best way to press things forward. -- Andrei
It's a painful proposition though. Can you see the pointless-ness of this feature and the effort being asked? It is against my interest to spend time (that I don't have) to make this feature work, when I am 100% convinced it is a massive anti-feature and I just want to see it ejected into space. It creates nothing but edges and offers nothing. Not a single advantage that anyone has yet been able present. The solution is simple, and solves every related issue instantly. There's no point wasting time identifying and fixing bugs in an implementation that shouldn't exist in the first place. This never should have happened, we can correct it easily, no effort from anyone is required, and we can all get on with something else. Do you also feel somehow emotionally attached to this? Give me a thread of logic to grasp on to; there is no way I can imagine to objectively balance the existence of this feature against the problems. We already see here demonstrated evidence of someone other than me going out of their way to awkwardly eliminate the namespace from existence. It should at least be opt-in by default.
From where I stand I see the following great ways to push things forward: 1. This code { ... } ought to compile with { these semantics } but does not.
 Anyway, I'm out, I'll be back when I find time for another round at this code.
Thanks! Andrei
Jan 11
parent Daniel N <ufo orbiting.us> writes:
On Tuesday, 12 January 2016 at 05:25:17 UTC, Andrei Alexandrescu 
wrote:
 1. This code { ... } ought to compile with { these semantics } 
 but does not.
This code... extern(C++, one) void fun1(); extern(C++, one) void fun2(); ... ought to compile. Considering that all scopes are closed in D, using the current semantics the short 'non-scope' version of extern is pointless, as one can at most ever bind to 1 symbol per namespace. For this reason I suggest to re-purpose it to NOT create a scope. This would allow the 'scoped' version of extern to remain as is: extern(C++, one) { } Not perfect, by any means since ideally both 'extern forms' should have identical semantics, but if the current auto-scoping feature is here to stay, then they anyway cannot ever be made to work with the same semantics(since scopes are closed). Maybe it's something both camps could live with? At least obsoleting tedious workarounds.
Jan 13
prev sibling parent Biotronic <simen.kjaras gmail.com> writes:
On Tuesday, 12 January 2016 at 04:29:00 UTC, Manu wrote:
 Can you see the pointless-ness of
 this feature and the effort being asked?
 It is against my interest to spend time (that I don't have) to 
 make
 this feature work, when I am 100% convinced it is a massive
 anti-feature and I just want to see it ejected into space. It 
 creates
 nothing but edges and offers nothing. Not a single advantage 
 that
 anyone has yet been able present.
 The solution is simple, and solves every related issue 
 instantly.
 There's no point wasting time identifying and fixing bugs in an
 implementation that shouldn't exist in the first place. This 
 never
 should have happened, we can correct it easily, no effort from 
 anyone
 is required, and we can all get on with something else.

 Do you also feel somehow emotionally attached to this? Give me 
 a thread of logic to grasp on to; there is no way I can imagine 
 to objectively balance the existence of this feature against 
 the problems. We already see here demonstrated evidence of 
 someone other than me going out of their way to awkwardly 
 eliminate the namespace from existence. It should at least be 
 opt-in by default.

 Anyway, I'm out, I'll be back when I find time for another 
 round at this code.
For what it's worth, I'm completely flabbergasted by the fact it somehow introduces a "named scope". So, my understanding of the pros: - It makes it easy to mirror the organization of your C++ code: Maybe. You probably already have thought of the organization of your modules, which takes care of that job for you in D. This seems to be the one selling point. If there are others, please do elucidate. Now, the cons: - No opt-out. There are workarounds, but that's not exactly a good argument in favor. - It can already be done with existing language features. This is in my opinion a big one. Whenever other language features are suggested, this argument is used to shoot it down. Why not so with this feature? - Implementation problems. Not exactly a heavy argument against a feature, but if there are many problems with it, it's a hint that the design may be flawed. The arguments (that I see) seem to favor not introducing a new symbol.
Jan 12