extern(C++, ns)

Marc Schütz via Digitalmars-d digitalmars-d at puremagic.com
Mon Jan 4 07:18:10 PST 2016


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.


More information about the Digitalmars-d mailing list