August 02, 2018
On 02/08/2018 8:59 PM, Walter Bright wrote:
> If this problem were to be solved, it should be solved, not hacked for one case only. There are many ways of dealing with it:
> 
> 1. pragma(mangle)
> 
> 2. change the names in the C/C++ side
> 
> 3. use a macro -Dwith=with_ when compiling the C/C++ code
> 
> 4. write wrappers/forwarders/trampolines in C/C++, compile them and link them in
> 
> 5. write a tool that patches the object file (not as hard as it sounds, the symbol table is usually in one spot, but of course the patcher would have to be implemented for each object file format). I've written object file patchers before, they work surprisingly well. Nobody else does it, presumably because the thought inspires terror :-)
> 
> 6. provide some switch to the D compiler to rename A=>B in the object file symbols, though I'd worry such would slow the compiler down
> 
> 7. perhaps amend the language such that an identifier of the form "__keyword" would appear in the object file as "keyword".

8. if any identifier starts with a keyword and ends with at minimum one _, one _ from the end of the identifier will be removed for mangling (but not e.g. lookup).
August 02, 2018
On Thursday, 2 August 2018 at 08:31:28 UTC, Walter Bright wrote:
> On 8/1/2018 10:06 PM, Johannes Pfau wrote:
>> I guess that would be acceptable if there is a real benefit, but I have
>> not seen a single argument for the current behavior in this thread.
>
> Please read my postings in this thread, then.

I know you have been very patient with explaining this, but I've been trying to read all threads on this topic and I'm still not sure, can you please acknowledge if I understood you correctly or not?

Let's use a simple pseudo example? Let's assume we have two different 'any' implementations...

The current extern(c++) design allows us to bind to both of them in a single file.

cpp_bindings.d
extern(c++, std)   ...any-definition...
extern(c++, boost) ...any-definition...

Personally I would never *bind* to two different namespaces in a single file, are there any other additional benefits to the current design which I'm overlooking?

With a non-scoped extern(c++) we could simply use two files.

cppstd/any.d
extern(c++, std)   ...any-definition...

boost/any.d
extern(c++, boost) ...any-definition...

My conclusion is that _if_ I understood you correctly, it must mean that in the examples which you have in mind, it is common to *bind* to two namespaces in the same file? Could you give a real-world examples of two namespaces which you would like to mix like that in the same *bindings* file? Is it for instance 'std' and 'std::experimental'?

August 02, 2018
On Wed, 01 Aug 2018 16:04:01 -0700, Walter Bright wrote:

> On 8/1/2018 10:24 AM, Jonathan M Davis wrote:
>> Not to say that that can't work, but I have to say that it seems pretty ugly if using extern(C++, NS) requires a bunch of aliases just to use symbols normally.
> 
> What is normal is a slippery concept, especially when one is comparing different lookup rules between languages. D modules do not a 1:1 correspondence with C++ namespaces, either (not even close).

Disclaimer: no knowledge or experience to back up my assumptions:


This is the part of the discussion I don't understand. Why do we need to care about [all of the] C++ lookup rules? Even if the D compiler has to know about them, I'd think it's an implementation detail on the D side that wouldn't necessarily need to be passed to the user.

If the goal is to link with C++ object files, the only thing that matters is what's available in those files, right? Anything to do with C++ rules that doesn't achieve this goal seems like it's just noise to me.
August 02, 2018
On Thursday, 2 August 2018 at 04:59:52 UTC, Walter Bright wrote:

> The difference is those names are supposedly in different namespaces, given that the code is converted from C++:
>
>     namespace ab { void foo(long); }
>     ... lots of code ...
>     namespace cd { void foo(int); }
>
> where the foo()'s do not conflict with each other, and a user would reasonably expect that same behavior when translated to D.

This is a trivial problem to solve.

mangle(C++, ab) { void foo(long); }
mangle(C++, cd) { void foo(int); }

It's certainly not obvious to me why anyone would do that, write

foo(3);

and then blame you when it doesn't work.
August 02, 2018
On 8/1/18 7:04 PM, Walter Bright wrote:
> On 8/1/2018 10:24 AM, Jonathan M Davis wrote:
>> Not to say that that can't work, but I have to say that it seems pretty ugly
>> if using extern(C++, NS) requires a bunch of aliases just to use symbols
>> normally.
> 
> What is normal is a slippery concept, especially when one is comparing different lookup rules between languages. D modules do not a 1:1 correspondence with C++ namespaces, either (not even close).
> 
> Aliases are a normal and highly useful D tool to copy names from one scope to another.
> 
> 
>> Certainly, it does come across like
>> you didn't trust the D module system to do its job for some reason.
> 
> Reorganizing the code into modules means potentially forcing users to split code from one C++ file into multiple D files. How's that really going to work if you have a translation tool? One of the aspects of Java I didn't care for was forcing each class into its own file.
> 
> So while Manu is clearly happy with cutting up a C++ file into multiple D files, I doubt that is universal. His proposal would pretty much require that for anyone trying to work with C++ namespaces who ever has a name collision/hijack or wants to make the code robust against collision/hijacking.
> 
> An example of silent hijacking:
> 
>     extern (C++, "ab") void foo(long); // original code
>     ... lots of code ...
>     extern (C++, "cd") void foo(int); // added later by intern, should have been
>                                       // placed in another module
>     ... a thousand lines later ...
>     foo(0); // OOPS! now calling cd.foo() rather than ab.foo(), D sux
> 
> You might say "nobody would ever write code like that." But that's like the C folks saying real C programmers won't write:
> 
>      int a[10];
>      for (int i = 0; i <= 10; ++i)
>         ...a[i]...
> 
> But we both know they do just often enough for it to be a disaster.

I challenge you to find any C++ code that has two identical function names in the same header file, but in different namespaces. I've done C++ development, but not really a C++ developer since about 2010 or so, but to me, this sounds like utter stupidity to do that. I think most of the issue with name conflict is between different *projects*, which is why you have a namespace to begin with.

In other words, libfoo defines foo, and libbar defines foo (how dare they!) and now there is a conflict, but you can distinguish by using foo::foo, and bar::foo. But it would be no different in D, since they would be in different libraries anyway, not in the same module.

I think comparing that to the <= problem is like apples and oranges. While the problem you identify *is* a problem, I believe it only exists on this thread, and not anywhere else.

-Steve
August 02, 2018
On 8/2/18 5:26 AM, Daniel N wrote:
> On Thursday, 2 August 2018 at 08:31:28 UTC, Walter Bright wrote:
>> On 8/1/2018 10:06 PM, Johannes Pfau wrote:
>>> I guess that would be acceptable if there is a real benefit, but I have
>>> not seen a single argument for the current behavior in this thread.
>>
>> Please read my postings in this thread, then.
> 
> I know you have been very patient with explaining this, but I've been trying to read all threads on this topic and I'm still not sure, can you please acknowledge if I understood you correctly or not?
> 
> Let's use a simple pseudo example? Let's assume we have two different 'any' implementations...
> 
> The current extern(c++) design allows us to bind to both of them in a single file.
> 
> cpp_bindings.d
> extern(c++, std)   ...any-definition...
> extern(c++, boost) ...any-definition...
> 
> Personally I would never *bind* to two different namespaces in a single file, are there any other additional benefits to the current design which I'm overlooking?
> 
> With a non-scoped extern(c++) we could simply use two files.
> 
> cppstd/any.d
> extern(c++, std)   ...any-definition...
> 
> boost/any.d
> extern(c++, boost) ...any-definition...
> 
> My conclusion is that _if_ I understood you correctly, it must mean that in the examples which you have in mind, it is common to *bind* to two namespaces in the same file? Could you give a real-world examples of two namespaces which you would like to mix like that in the same *bindings* file? Is it for instance 'std' and 'std::experimental'?
> 

The example that Walter keeps bringing up is one where the C++ code has 2 namespaces in the same header file. Not only that, but then identically named functions in those namespaces. In that case, a direct translation would cause problems with hijacking in D, where it doesn't in C++ (as long as you don't ever use `using` declarations, or only use one or the other).

So the difference from your example is that you're not trying to bind 2 different files with 2 different namespaces into one D module, but you are translating a single C++ header file that's written with the 2 bindings as described. Not std and boost, but ns1 and ns2 inside the same header file, which each have identical symbols.

I've never seen it, but it's certainly valid C++ and in the realm of possibility.

-Steve
August 03, 2018
On 03/08/2018 12:24 AM, Steven Schveighoffer wrote:
> The example that Walter keeps bringing up is one where the C++ code has 2 namespaces in the same header file. Not only that, but then identically named functions in those namespaces. In that case, a direct translation would cause problems with hijacking in D, where it doesn't in C++ (as long as you don't ever use `using` declarations, or only use one or the other).
> 
> So the difference from your example is that you're not trying to bind 2 different files with 2 different namespaces into one D module, but you are translating a single C++ header file that's written with the 2 bindings as described. Not std and boost, but ns1 and ns2 inside the same header file, which each have identical symbols.
> 
> I've never seen it, but it's certainly valid C++ and in the realm of possibility.
> 
> -Steve

That's easy to solve.

Split into a package, public import each file and alias if required to get each version.

It's easy to work around and most importantly, reasonable.
August 02, 2018
On Thursday, 2 August 2018 at 12:30:14 UTC, rikki cattermole wrote:
> On 03/08/2018 12:24 AM, Steven Schveighoffer wrote:
>> 
>> I've never seen it, but it's certainly valid C++ and in the realm of possibility.
>> 
>> -Steve
>

I see, thanks.

> That's easy to solve.
>
> Split into a package, public import each file and alias if required to get each version.
>
> It's easy to work around and most importantly, reasonable.

Agreed.
August 02, 2018
On Thu, 2 Aug 2018 at 02:05, Walter Bright via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
> On 8/1/2018 11:08 PM, Manu wrote:
> > We have demonstrated consistent ongoing issues and frustration for 6 years.
>
> Have you ever tried the alias method I proposed?

Of course, it's the only tool we have here, and a major source of my
frustration!
Every time I type alias this way, I have thoughts that make baby Jesus cry.
August 02, 2018
On 8/2/2018 2:05 AM, rikki cattermole wrote:
> 8. if any identifier starts with a keyword and ends with at minimum one _, one _ from the end of the identifier will be removed for mangling (but not e.g. lookup).

This will break existing code. A double underscore prefix is reserved for the implementation, which is why I went down that path.