July 29, 2018
On Sunday, 29 July 2018 at 03:20:29 UTC, Walter Bright wrote:
> On 7/28/2018 11:18 AM, Manu wrote:
>> Make a PR that implements namespace as a string... I will use that fork of D forever.
>
> 1. Look how it is mangled on the C++ side. (Use "grep" on the object file.)
>
> 2. Use:
>
>    pragma(mangle, "the mangled name")

That a) doesn't scale in a real dynamic codebase (think templates), and b) is platform dependent and so isn't a proper solution.

Honestly the only problem with Manu's suggestion is you can't expose `a::foo` and `b::foo` with the same signature within the same module due to (D) name collisions, although I don't see any reason why we can't do both.

Then again I don't see any (non philosophical/compiler front end internal) issue why you can't reopen a namespace. D is supposed to be pragmatic, after all.
July 29, 2018
On Sunday, 29 July 2018 at 03:20:29 UTC, Walter Bright wrote:
> On 7/28/2018 11:18 AM, Manu wrote:
>> Make a PR that implements namespace as a string... I will use that fork of D forever.
>
> 1. Look how it is mangled on the C++ side. (Use "grep" on the object file.)
>
> 2. Use:
>
>    pragma(mangle, "the mangled name")

People are trying to read C++ header files and convert the declarations ... how is that supposed to work? Even if they were manually adding declarations, this doesn't sound like a feasible approach.
July 29, 2018
On 7/28/2018 11:06 PM, Nicholas Wilson wrote:
> Then again I don't see any (non philosophical/compiler front end internal) issue why you can't reopen a namespace. D is supposed to be pragmatic, after all.

Consider if a template reopens a namespace and throws a few more overloads in it. Then, what's in the namespace is dependent on which expansions are done, in which order. Throw in the inevitable circular references. Do people write code like that? Sure as shootin', they do, and they demand that it work, and file lots of bug reports about the erratic behavior.

Next, consider a function body throwing a few more overloads in. Now, if the function body is compiled or not (and the compiler tries to avoid compiling bodies unless it has to) affects code that is outside of the function.

C++ is full of stuff like that. The difference is, when code fails in some bizarre way, programmers blame themselves and throw money at Scott Meyers to educate them on how to avoid writing such code. For D, they blame me.

The last time we fixed scope lookup to make it more complicated was with imports, and that took YEARS to sort out.

So I'm a little reluctant to add features that will result in a rat's nest of problems I can neither explain nor fix, then someone will add 4000 incomprehensible lines to fix 2 cases and add 5 or 6 bizarre regressions in the process and people complain the compiler is unstable. :-)
July 29, 2018
On 7/28/2018 9:23 PM, Manu wrote:
> Don't troll me on this one, this is a very sensitive topic!
> I could have a legit mental breakdown ;)


Here's another method:

------
extern (C++, ns) { int foo() { return 1; } }

mixin template X()
{
  extern (C++, ns) { int bar() { return 2; } }
}

mixin X!() x;

-------

and another:

-----
extern (C++, ns) { int foo() { return 1; } }

struct S
{
  extern (C++, ns) { int bar() { return 2; } }
}
----
July 29, 2018
On Sun., 29 Jul. 2018, 12:40 am Walter Bright via Digitalmars-d, < digitalmars-d@puremagic.com> wrote:

> On 7/28/2018 11:06 PM, Nicholas Wilson wrote:
> > Then again I don't see any (non philosophical/compiler front end
> internal) issue
> > why you can't reopen a namespace. D is supposed to be pragmatic, after
> all.
>
> Consider if a template reopens a namespace and throws a few more overloads
> in
> it. Then, what's in the namespace is dependent on which expansions are
> done, in
> which order. Throw in the inevitable circular references. Do people write
> code
> like that? Sure as shootin', they do, and they demand that it work, and
> file
> lots of bug reports about the erratic behavior.
>
> Next, consider a function body throwing a few more overloads in. Now, if
> the
> function body is compiled or not (and the compiler tries to avoid
> compiling
> bodies unless it has to) affects code that is outside of the function.
>
> C++ is full of stuff like that. The difference is, when code fails in some
> bizarre way, programmers blame themselves and throw money at Scott Meyers
> to
> educate them on how to avoid writing such code. For D, they blame me.
>
> The last time we fixed scope lookup to make it more complicated was with imports, and that took YEARS to sort out.
>
> So I'm a little reluctant to add features that will result in a rat's nest
> of
> problems I can neither explain nor fix, then someone will add 4000
> incomprehensible lines to fix 2 cases and add 5 or 6 bizarre regressions
> in the
> process and people complain the compiler is unstable. :-)
>

I don't understand your claims that it would somehow become problematic or incomprehensible.

Are you saying D's module system is incomprehensible?

All we're asking for is that C++ namespaces do **nothing** except affect
the mangling.
We want the D module system to work verbatim, without any new behaviours or
edge cases of any kind.
All symbols are normal symbols in their normal D module namespaces, and
resolved according to all the normal name lookup rules... just the symbol
mangling will make it link properly, just like extern(C) and extern(C++).

You're insisting we accept this complex solution you cooked up with new scopes introduced which are not module scopes, and introduce practical problems for most that try and use it, and then somehow tell us that we're asking to complicate the language when we beg for normal D behaviour as an option... It doesn't make sense.

We don't want to 'open' or 'reopen' a namespace. We just want to tell the function how to mangle right.

Show me "4000 incomprehensible lines" that were introduced by the existence of extern(C) or extern(C++)? Because asking for a namespace as nothing more than a mangling attribute will have no further effect than any other extern statement; that's the point!

>


July 29, 2018
On 7/29/2018 1:15 AM, Manu wrote:
> All we're asking for is that C++ namespaces do **nothing** except affect the mangling.

If I do that, the next bug report will be:

  extern (C++, "ab") { void foo(); }
  extern (C++, "cd") { void foo(); } // Error, foo() is already declared

  foo(); // which one gets called?

The reason namespaces were added to C++ is to not have such name collisions. Namespaces in C++ introduce a scope. D cannot interoperate with this without introducing a scope as well.
July 29, 2018
The name can be "transferred" into the global namespace using an alias.

This boilerplate can all be put inside of a string mixin.
July 29, 2018
On Sunday, July 29, 2018 2:28:08 AM MDT Walter Bright via Digitalmars-d wrote:
> On 7/29/2018 1:15 AM, Manu wrote:
> > All we're asking for is that C++ namespaces do **nothing** except affect the mangling.
>
> If I do that, the next bug report will be:
>
>    extern (C++, "ab") { void foo(); }
>    extern (C++, "cd") { void foo(); } // Error, foo() is already declared
>
>    foo(); // which one gets called?
>
> The reason namespaces were added to C++ is to not have such name collisions. Namespaces in C++ introduce a scope. D cannot interoperate with this without introducing a scope as well.

I guess that the argument at that point is that you would have to put them in separate D modules, just like you would if they were extern(D) functions. If that were the only problem, then that doesn't sound like a big one - especially if the documentation made it very clear that extern(C++) declarations did not affect the lookup rules, thus forcing you to rely on D's module system to deal with it all. All the extern(C++, NS) stuff does at that point is to enable linking with C++ and forces all of the normal D rules, which at least _sounds_ like it would be straightforward. If anything, it seems like it would make things much simpler.

However, I've done nothing with C++ namespaces in D thus far. So, I really can't comment on the problems beyond what I've read in threads like this one.

- Jonathan M Davis



July 29, 2018
On Sunday, 29 July 2018 at 11:03:43 UTC, Jonathan M Davis wrote:
> I guess that the argument at that point is that you would have to put them in separate D modules, just like you would if they were extern(D) functions.

Yep, that'd sound acceptable to me, implying that

```
extern(C++, cppns) { void foo(); }
void foo();
```

wouldn't work anymore, and particularly, this neither:

```
extern(C++, cppns)
{
    extern(C++, nested) { void foo(); }
    void foo();
}
```

so that a straight C++ namespace => D module hierarchy mapping would probably be required in the general case:

```
// cppns/package.d
module cppns;
extern(C++, cppns) { void foo(); }

// cppns/nested/package.d
module cppns.nested;
extern(C++, cppns) extern(C++, nested) { void foo(); }
```

July 29, 2018
On Sunday, 29 July 2018 at 08:28:08 UTC, Walter Bright wrote:
> On 7/29/2018 1:15 AM, Manu wrote:
>> All we're asking for is that C++ namespaces do **nothing** except affect the mangling.
>
> If I do that, the next bug report will be:
>
>   extern (C++, "ab") { void foo(); }
>   extern (C++, "cd") { void foo(); } // Error, foo() is already declared
>
>   foo(); // which one gets called?
>
> The reason namespaces were added to C++ is to not have such name collisions. Namespaces in C++ introduce a scope. D cannot interoperate with this without introducing a scope as well.

Wouldn't something like this would prevent that :

   extern (C++, "ab") { void foo(); }
   extern (C++, "cd", "s") { void foo(); } // s is an optional D scope

   foo(); // works
   s.foo(); // works too

Of course, it will imply some syntax change on the extern keyword, as a new optional parameter will be added.