Re: Is there any good reason why C++ namespaces are "closed" in D?
On 8/7/2018 3:49 AM, Atila Neves wrote: Yes, I've already implemented it. Wonderful! I'm not sure what the impact will be with nested namespaces in real headers. I guess we'll have to see. Yes.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Tuesday, 7 August 2018 at 02:25:32 UTC, Walter Bright wrote: Let's see if we can find some common ground. The boilerplate I suggested seems to enable DPP to generate working code that behaves "as if" the namespace scope is not there, even for nested namespaces. Is this correct? Yes, I've already implemented it. I'm not sure what the impact will be with nested namespaces in real headers. I guess we'll have to see.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 8/7/2018 12:08 AM, Nicholas Wilson wrote: I don't see what making an alias to a namespace has to do with it. That was your suggested workaround, was it not? No, it was not. It was about making an alias to the members of the namespace.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 8/7/2018 1:13 AM, Walter Bright wrote: On 8/7/2018 12:08 AM, Nicholas Wilson wrote: I don't see what making an alias to a namespace has to do with it. That was your suggested workaround, was it not? No, it was not. It was about making an alias to the members of the namespace. BTW, the mass confusion and misunderstandings in this thread is why Manu should write a DIP.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Tuesday, 7 August 2018 at 02:25:32 UTC, Walter Bright wrote: Let's see if we can find some common ground. The boilerplate I suggested seems to enable DPP to generate working code that behaves "as if" the namespace scope is not there, even for nested namespaces. Is this correct? Almost. extern(C++, noise1.noise2.noise3) void fun(); alias fun = noise1.noise2.noise3.fun; void main() { fun(1); } Except the full name bleeds to the user | | V my.d(4): Error: function my.noise1.noise2.noise3.fun() is not callable using argument types (int) Would you prefer to: 1) Keep as is, let it bleed 2) Suppress namespaces when printing error messages 3) Never generate the namespace in the first-place
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Tuesday, 7 August 2018 at 05:58:17 UTC, Walter Bright wrote: On 8/6/2018 8:14 PM, Nicholas Wilson wrote: Yes, but only for a single instance of the namespace. In the general case no, see the first reply in https://forum.dlang.org/post/xdaedmlbbqtztiqcw...@forum.dlang.org The idea is to not have a namespace That is what we have been arguing for all thread... I don't see what making an alias to a namespace has to do with it. That was your suggested workaround, was it not? If not you have _really_ lost me.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 8/6/2018 8:14 PM, Nicholas Wilson wrote: Yes, but only for a single instance of the namespace. In the general case no, see the first reply in https://forum.dlang.org/post/xdaedmlbbqtztiqcw...@forum.dlang.org The idea is to not have a namespace, I don't see what making an alias to a namespace has to do with it.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Tuesday, 7 August 2018 at 02:25:32 UTC, Walter Bright wrote: Let's see if we can find some common ground. The boilerplate I suggested seems to enable DPP to generate working code that behaves "as if" the namespace scope is not there, even for nested namespaces. Is this correct? Yes, but only for a single instance of the namespace. In the general case no, see the first reply in https://forum.dlang.org/post/xdaedmlbbqtztiqcw...@forum.dlang.org
Re: Is there any good reason why C++ namespaces are "closed" in D?
Let's see if we can find some common ground. The boilerplate I suggested seems to enable DPP to generate working code that behaves "as if" the namespace scope is not there, even for nested namespaces. Is this correct?
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 8/5/2018 9:53 PM, Manu wrote: If we produce a DIP to fix this, will you reject it in principle? Producing a DIP is a good idea, it provides an anchor point for any future discussion of the topic, rather than the tangle and noise that is this thread. It is an ample opportunity to put the best foot forward on your ideas. I'm not going to categorically say we'll reject it, but will say that you'll need to make a more compelling case, and a DIP is the right method for that. Please keep in mind that a good DIP will address the counterarguments and other methods of solving the issue. As this thread affirms, trying to design things in the forums doesn't work very well, and I should have asked for a DIP in the first place.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 8/6/2018 3:19 PM, tide wrote: That's just a deflection, 1. I'm only here to help, and am not interested in scoring debate points. 2. To bring up other topics, please start a new thread. Especially since this one is quite voluminous.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Monday, 6 August 2018 at 20:35:37 UTC, Walter Bright wrote: On 8/6/2018 11:26 AM, tide wrote: What's your crossplatform workaround if I have a namespace named "version" or "package" ? See my reply to Rick Cattermole. https://digitalmars.com/d/archives/digitalmars/D/Is_there_any_good_reason_why_C_namespaces_are_closed_in_D_317277.html#N317507 But that's not currently implemented is it? Your proposed solution adds an exception to the rule that just increases complexity of the language. No where else does "__" remove itself from the name it is used with. With the syntax extern(C++, "...") it is more easily understood, no crazy exceptions need to be made. You also didn't mention your reasoning behind not including a way to use const pointers to mutable data. That's a longstanding issue and has nothing to do with namespaces. That's just a deflection, we are talking about C++ name mangling, not namespaces. How do you mangle const pointers to mutable data in D to be able to call C++ ? You don't need to implement the feature, you just need a way to create the C++ mangle, which there is none. The only way is to change C++ code, like you said, telling people to rewrite their code is never, ever going to work.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 8/6/2018 11:26 AM, tide wrote: What's your crossplatform workaround if I have a namespace named "version" or "package" ? See my reply to Rick Cattermole. https://digitalmars.com/d/archives/digitalmars/D/Is_there_any_good_reason_why_C_namespaces_are_closed_in_D_317277.html#N317507 You also didn't mention your reasoning behind not including a way to use const pointers to mutable data. That's a longstanding issue and has nothing to do with namespaces. How can you suggest DPP then go on to say you've never even used it or know how it is even used? Because I have full confidence in Atila and Laeeth. I've also written such a translator myself (HTOD) so I know what they're capable of.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Friday, 3 August 2018 at 21:20:37 UTC, Walter Bright wrote: Yes. But then you'll have the people who want a 1:1 correspondence with their C++ files and the corresponding D files. I happen to be one of those people, for the ease of maintaining a translation (and for comparing it with the original C++ source code if it is not behaving correctly). This would still be true if current behavior was kept and extern(C++, "ns") or extern(C++, ns, noscope) or something was added though no? Though I do think the string is superior though because then this would actually compile: extern(C++, "shared") { void f(); } It feels the two preferences being mutually exclusive has somehow occupied a lot of this discussion when they are not. Cheers, - Ali
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Sunday, 5 August 2018 at 23:28:06 UTC, Walter Bright wrote: On 8/4/2018 12:45 AM, Manu wrote: [...] I get it, Manu, you don't find my arguments compelling. You've put these forth before, and I could repeat myself rebutting each. I expect we're at a dead end with that. But the fact remains, I've shown both you and Atila how to make things work for you, in a hygienic manner, with the language as it is now. For you, it's adding an alias declaration. For Atila, it's a couple lines of boilerplate dpp can add, without disrupting dpp's internal design. What's your crossplatform workaround if I have a namespace named "version" or "package" ? extern(C++, version) // error { void foo(); } extern(C++, package) // error { void bar(); } You also didn't mention your reasoning behind not including a way to use const pointers to mutable data. The only workaround that exists currently is to rewrite C++ code, which you stated wasn't a valid solution you considered for extern(C++). I understand you don't want to type in the alias declaration. May I suggest using Atila's dpp? Then you won't have to even look at the output. I also expect that your use cases can help make dpp better, and that would be good for all of us. --- P.S. I have no experience with dpp and how it is used. But my experience with translators is that nobody expects to nor wants to look at its output. They just want it to work. And it seems a fact of life that the output of machine translation resists being purty, because what's purty in A never looks purty in B. How can you suggest DPP then go on to say you've never even used it or know how it is even used?
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Saturday, 4 August 2018 at 12:18:21 UTC, tide wrote: On Saturday, 4 August 2018 at 01:45:44 UTC, Laeeth Isharc wrote: On Friday, 3 August 2018 at 22:55:51 UTC, Rubn wrote: The difference is they would have to rework their existing code. If you are writing D source code bindings for your code, then you are essentially writing new code. You don't have to worry about backwards compatibility. Why would you write bindings if the computer can do it for you, better, faster and consistently? With the current tools the ones that generate D files to be used aren't very good. They evaluate Macros based on the current implementation, so if there's a define MACHINE_X86 or MACHINE_x64, those macro and #if's will be evaluated based on the current system running the tool instead of generating equivalent version() statements. If the D files are to be checked in, then yes, that'd be a problem. If they're not, as is the case with dpp, then... that's actually what you want. dpp: I fought the preprocessor and the preprocessor won. It would be, but I don't think it'll ever be 100% and will require manual intervention. If manual intervention is required, dpp has failed. Some problems will be tricky, especially where the preprocessor is concerned. But a lot of real-life production code works.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Saturday, 4 August 2018 at 07:34:49 UTC, Manu wrote: On Fri, 3 Aug 2018 at 18:50, Laeeth Isharc via Digitalmars-d wrote: [...] Faster and consistently, sure. But I don't think 'better' is possible. [...] Bindings != wrappers. I agree that wrappers will nearly always need to be written, I'm trying to automate the writing of the declarations needed to link. It should be possible to automate translating everything, but some things will be tricky in C++. std::vector is quite clearly a value type, yet the GNU implementation declares it as a class with protected inheritance from _Vector_base. That's going to be fun...
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Friday, 3 August 2018 at 21:49:53 UTC, Walter Bright wrote: On 8/3/2018 3:58 AM, Atila Neves wrote: I would only be able to alias a nested namespace once, since the code below obviously won't work: mixin CppNamespace0!() x; alias chrono = x.std.chrono; mixin CppNamespace1!() y; alias chrono = y.std.chrono; Try this: mixin template X() { // boilerplate prefix extern (C++, std) extern(C++, chrono) int foo(); // original line } mixin X!() x; alias foo = x.std.chrono.foo; // boilerplate suffix That doesn't solve the problem at all. I was toying with being able to have a nested namespace be an alias in a module. I can't realias chrono after the first `alias chrono = `, nor can I alias it to the different `chrono`s in all the different template mixins. I considered for a while whether or not this would be truly bad, and the more I think about it the more convinced I am that Manu is right and there should be _no_ scoping whatsoever in D regarding C++ namespaces. We have packages and modules, we can use those to put the C++ functions we declare in whatever hierarchy we want. I am puzzled. With: namespace std { namespace chrono { void foo(); } } namespace std { namespace chrono { void bar(); } } you have stated that it is impractical for your translator to rewrite this as: namespace std { namespace chrono { void foo(); void bar(); } } Ok, I get that. But it is practical to rewrite it as: module std.chrono; void foo(); void bar(); ? I don't understand what your question has to do with what you quoted. What I'm trying to say is that I think `extern(C++, foo.bar)` should NOT introduce a scope in D in any way, shape, or form. The D module/import/overload system should have no idea of what `foo` or `foo.bar` are - they don't exist. > I mean `std` should never be part of the fully qualified name of, for > instance, `core.stdcpp.exception.std.bad_exception`. It should just > be `core.stdcpp.exception.bad_exception` instead. C++ recognizes that, too, which is why it has "using" declarations. D has the equivalent thing, "alias". You can do things like: import std = core.stdcpp.exception; and then refer to: std.bad_exception or: import exception = core.stdcpp.exception; exception.bad_exception; or whatever works best for one's project. Aliasing and import renaming (which are really just more aliasing) is very capable, and was designed for just these sorts of issues. I think we're talking past each other. I know how to alias in D, and how to use `using` in C++. What I'm saying is that, with the file we have now (core.stdcpp.exception): extern(C++, std) { class exception { /* ... */ } } Currently the fully qualified name of `exception` is `core.stdcpp.exception.std.exception`. I'm arguing that this is a mistake, and the the FQN should instead be `core.stdcpp.exception.exception`. Yes, namespaces introduce scope in C++. Yes, lookup rules in C++ are crazy. The main points I'm (and, I think, Manu) arguing are: 1. We already have D packages, modules, and overload rules. We don't need to import any from C++ 2. That namespaces introduce a scope in C++ does not mean that `extern(C++, ns)` should introduce one in D i.e. Keep everything about D as-is, _except_ for no scoping for `extern(C++, ns)`.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Monday, 6 August 2018 at 09:48:30 UTC, Danni Coy wrote: Outside perspective here and possibly stupid question. Is there any way we could have our cake and eat it too? One of the thinks I like is that it tends to be much more readable than C++, more code than necessary hurts readability of that code. Can the compiler warn when a function is called that is shadowed by another function in a different namespace. This to me seems like the most sane solution, what am I missing? I haven't read all of the posts in this thread, but my understanding of Walter's argument is that he believes there is only one correct way to work with C++ code. If that's the case, there's no need for warnings, because the language should prevent you from doing it wrong in the first place. The first step will be to convince him that the "mangle only" approach is valid.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Monday, 6 August 2018 at 04:53:05 UTC, Manu wrote: If we produce a DIP to fix this, will you reject it in principle? I think you and Walter Bright made good points and I think a creation of a DIP that addresses his concerns would be a best course of action IMO. -Alexander
Re: Is there any good reason why C++ namespaces are "closed" in D?
Outside perspective here and possibly stupid question. Is there any way we could have our cake and eat it too? One of the thinks I like is that it tends to be much more readable than C++, more code than necessary hurts readability of that code. Can the compiler warn when a function is called that is shadowed by another function in a different namespace. This to me seems like the most sane solution, what am I missing? On Mon, Aug 6, 2018, 14:53 Manu via Digitalmars-d < digitalmars-d@puremagic.com> wrote: > On Sun, 5 Aug 2018 at 16:30, Walter Bright via Digitalmars-d > wrote: > > > > On 8/4/2018 12:45 AM, Manu wrote: > > > [...] > > I get it, Manu, you don't find my arguments compelling. You've put these > forth > > before, and I could repeat myself rebutting each. I expect we're at a > dead end > > with that. > > So, what you're saying is "I hear you, and I will never change it > because I subjectively prefer it the way it is in spite of every users > experience". > Will you commit to that position officially, so we can refer back to > it in future? > > Just support the string namespace? It won't hurt you, our code will be > better, and you'll make us all that actually link to C++ so much > happier for it. > > If we produce a DIP to fix this, will you reject it in principle? >
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Sun, 5 Aug 2018 at 16:30, Walter Bright via Digitalmars-d wrote: > > On 8/4/2018 12:45 AM, Manu wrote: > > [...] > I get it, Manu, you don't find my arguments compelling. You've put these forth > before, and I could repeat myself rebutting each. I expect we're at a dead end > with that. So, what you're saying is "I hear you, and I will never change it because I subjectively prefer it the way it is in spite of every users experience". Will you commit to that position officially, so we can refer back to it in future? Just support the string namespace? It won't hurt you, our code will be better, and you'll make us all that actually link to C++ so much happier for it. If we produce a DIP to fix this, will you reject it in principle?
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 8/2/2018 5:23 PM, rikki cattermole wrote: Because it will affect mangling only, do we have any examples of c/c++ code that appends _'s to it that is used by the D community? The __ scheme won't break existing code, and we don't need a survey to show that.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 8/4/2018 12:45 AM, Manu wrote: [...] I get it, Manu, you don't find my arguments compelling. You've put these forth before, and I could repeat myself rebutting each. I expect we're at a dead end with that. But the fact remains, I've shown both you and Atila how to make things work for you, in a hygienic manner, with the language as it is now. For you, it's adding an alias declaration. For Atila, it's a couple lines of boilerplate dpp can add, without disrupting dpp's internal design. I understand you don't want to type in the alias declaration. May I suggest using Atila's dpp? Then you won't have to even look at the output. I also expect that your use cases can help make dpp better, and that would be good for all of us. --- P.S. I have no experience with dpp and how it is used. But my experience with translators is that nobody expects to nor wants to look at its output. They just want it to work. And it seems a fact of life that the output of machine translation resists being purty, because what's purty in A never looks purty in B.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Saturday, 4 August 2018 at 17:54:11 UTC, Jonathan M Davis wrote: On Saturday, August 04, 2018 12:18:21 tide via Digitalmars-d wrote: The only person I've seen that wants this is Walter. I haven't seen anyone else show interest in wanting a 1:1 correlation. It's unreasonable, D isn't C++ nor should it be trying to strive to be C++. In general, it's easier for maintenance if there's a 1:1 correlation between C/C++ headers and D headers. It makes it easier to update the D files, and it makes it easier to find where something is in the D translation if you're already familiar with the C/C++ version - or if you're reading documentation for the C/C++ version and trying to translate that into what you need to know to use the D version. For the most part, the C bindings in druntime follow the layout of the C headers that they correspond to precisely because doing so is more maintainable and easier to navigate than if the D modules were laid in a hierarchy that followed its own logic instead of trying to emulate the layout of the C headers being translated. In fact, some of the more annoying issues with the C header translations in druntime come from places where the layout of the C headers was not quite followed for one reason or another. So, I'd fully expect most C/C++ binding projects to have a 1:1 correlation between C/C++ headers and D headers, and I don't think that Walter is at all misguided in that respect. That being said, in most cases, such a 1:1 translation would work just fine if we had extern(C++, "NS"), and it just affected name mangling. There would be corner cases where it did not, but they could be worked around even if it meant that in that particular case, you lost the 1:1 translation - but as Steven pointed out, it actually would be pretty straightforward to manually add the kind of namespace wrappers that the language currently forces on you with extern(C++, NS) if we had extern(C++, "NS"). And of course, if we actually ended up with both extern(C++, "NS"), and extern(C++, NS), then you could just use the extern(C++, NS) construct in those corner cases, though ultimately, I think that we'd be better off with just having extern(C++, "NS"). So, I don't think that Walter is being misguided here in terms of how he expects folks to be translating C++ headers. I just think that his concern over some corner cases you get with bad C++ code has caused him to make the current solution for binding to C++ namespaces more complicated than it needs to be. And I don't think that his concerns are misguided either. I just think that he's just blowing them out of proportion given how easy it would be to work around those issues with the solution that Manu wants, whereas the common case suffers with the current solution. - Jonathan M Davis Alright that's fair but it still isn't ever going to be 1:1. I've done some stuff with C++ that used the fact that including headers is just a copy and paste. So I had header files that didn't have structures defined in them. You would define the structures before the including the header file so that it could be used with multiple different headers. There's no way you are ever going to get a 1:1 mapping of that into D. Let alone remotely similar, it would have to be completely different. It's nice to have but you are never going to achieve a complete 1:1 mapping unless you bring all of C++'s features. Even with the current implementation it doesn't allow multiple namespaces of the same name in the same D module. Yet Walter is hung up on that fact of that one edge case.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Saturday, August 04, 2018 12:18:21 tide via Digitalmars-d wrote: > The only person I've seen that wants this is Walter. I haven't > seen anyone else show interest in wanting a 1:1 correlation. It's > unreasonable, D isn't C++ nor should it be trying to strive to be > C++. In general, it's easier for maintenance if there's a 1:1 correlation between C/C++ headers and D headers. It makes it easier to update the D files, and it makes it easier to find where something is in the D translation if you're already familiar with the C/C++ version - or if you're reading documentation for the C/C++ version and trying to translate that into what you need to know to use the D version. For the most part, the C bindings in druntime follow the layout of the C headers that they correspond to precisely because doing so is more maintainable and easier to navigate than if the D modules were laid in a hierarchy that followed its own logic instead of trying to emulate the layout of the C headers being translated. In fact, some of the more annoying issues with the C header translations in druntime come from places where the layout of the C headers was not quite followed for one reason or another. So, I'd fully expect most C/C++ binding projects to have a 1:1 correlation between C/C++ headers and D headers, and I don't think that Walter is at all misguided in that respect. That being said, in most cases, such a 1:1 translation would work just fine if we had extern(C++, "NS"), and it just affected name mangling. There would be corner cases where it did not, but they could be worked around even if it meant that in that particular case, you lost the 1:1 translation - but as Steven pointed out, it actually would be pretty straightforward to manually add the kind of namespace wrappers that the language currently forces on you with extern(C++, NS) if we had extern(C++, "NS"). And of course, if we actually ended up with both extern(C++, "NS"), and extern(C++, NS), then you could just use the extern(C++, NS) construct in those corner cases, though ultimately, I think that we'd be better off with just having extern(C++, "NS"). So, I don't think that Walter is being misguided here in terms of how he expects folks to be translating C++ headers. I just think that his concern over some corner cases you get with bad C++ code has caused him to make the current solution for binding to C++ namespaces more complicated than it needs to be. And I don't think that his concerns are misguided either. I just think that he's just blowing them out of proportion given how easy it would be to work around those issues with the solution that Manu wants, whereas the common case suffers with the current solution. - Jonathan M Davis
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Friday, 3 August 2018 at 21:20:37 UTC, Walter Bright wrote: If we want to support interfacing with C++, we have to support badly written C++, because that is the NORMAL case. Telling them their code is and that they should rewrite it in order to work with D is never, ever going to work. On another note, why aren't const pointers to mutable data supported then? Anytime I need to write a wrapper for a function that has a parameter "T* const" I have to rewrite the C++ code cause there's no cross-platform way to mangle and call that function from D. Does this mean you are for const pointers in D now or is trying to make D into C++ unreasonable now ?
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Saturday, 4 August 2018 at 01:45:44 UTC, Laeeth Isharc wrote: On Friday, 3 August 2018 at 22:55:51 UTC, Rubn wrote: The difference is they would have to rework their existing code. If you are writing D source code bindings for your code, then you are essentially writing new code. You don't have to worry about backwards compatibility. Why would you write bindings if the computer can do it for you, better, faster and consistently? With the current tools the ones that generate D files to be used aren't very good. They evaluate Macros based on the current implementation, so if there's a define MACHINE_X86 or MACHINE_x64, those macro and #if's will be evaluated based on the current system running the tool instead of generating equivalent version() statements. That's the idea behind DPP. You can just #include C headers and they will be translated before compile time. This is very helpful with projects like HDF5 that consider it acceptable in a minor release to replace a function with a macro. Wrappers are a bit different. In time C++ will follow. I wouldn't call that the same thing as what generally defines a wrapper. It's a different concept that does the work at compiler time. If I remember correctly Clang has something similar, where two languages can call each other once they have been compiled to Clang's intermediate format. Or at least it was something that was being worked on a while ago, never used it though. Not only that, who do you think even writes bindings for libraries? Most bindings are done by the community for libraries to other languages. How many companies do you know have bindings for their C/C++ libraries for D, that maintains them? We do for a few things - for other peoples' libraries not our own. But it would be better not to have to write bindings at all. It would be, but I don't think it'll ever be 100% and will require manual intervention. damn hell no. That's what modules are for. So why are you trying to implement namespaces in D under the guise of C++ name mangling. I don't think either Manu or Atila want to be able to sneak in namespaces by the backdoor. They just want to be able easily to control namespace mangling of C++ linkage symbols. Never said they did, but that's what Walter and the current implementation seem to indicate. I'd rather just have extern(C++) be what extern(C++) and extern(D) do, just change the name mangling, not try to emulate some features of namespaces like it currently does. What extern(C++) should be used for is allowing you to call C++ code from D, not to be able to format C++ code into D. The only problem you have with breaking code up into multiple files is that it isn't 1:1. That's not a technical problem, it's a problem of conflicting personal opinion. If it's not 1:1, who cares? If some some odd reason you have two namespaces in one file in C++, odds are they are probably separated in that one file anyway. If not and for some reason the the code has multiple namespace definitions smashed together into one file, flip-floping between namespaces. That's not D's problem to fix the project's poor organization method. For automatically translated bindings I think that the request is not unreasonable because there's considerable value in being able to just #include C++ headers as you can already with C headers and just call the C++ code from D. D doesn't have libraries? Well it's got 1500 on code.dlang.org plus C and C++ libraries. What is it you think is missing? That's a good retort! I understand from Atila present choice just makes it a lot more complicated, not impossible. The only person I've seen that wants this is Walter. I haven't seen anyone else show interest in wanting a 1:1 correlation. It's unreasonable, D isn't C++ nor should it be trying to strive to be C++. Where are const pointers? Where are default constructors for structs that make structs not POD anymore, that changes the calling convention used in C++ (on Windows at least).
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 8/3/18 5:20 PM, Walter Bright wrote: Telling them their code is and that they should rewrite it in order to work with D is never, ever going to work. And that's OK with me. I'm OK with D saying it only supports reasonably written C++ code, and 99% of the C++ community would agree. If that means we lose one "customer" who doesn't use sane namespace practices, then I guess they can stick with C++. 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. Yes. But then you'll have the people who want a 1:1 correspondence with their C++ files and the corresponding D files. I happen to be one of those people, for the ease of maintaining a translation (and for comparing it with the original C++ source code if it is not behaving correctly). I have to take this to mean that you are someone who wants 1:1 correspondence, and not someone who puts 2 namespaces in the same file with identical symbol names. In either case, I think it's forgivable for D to not be able to completely mimic C++ in every possible manner. Besides, I provided solutions for both Manu's case and Atila's (they are different), which are easier than "simply" breaking things up into multiple files. But the solution is crazy backwards. You should be able to put in weird aliases and namespaces (or even split into multiple modules) if you have really crappy C++ code with namespace issues. Aliases and bizarre mixins shouldn't be the default *just in case* you have crappy code. Note, I can do this to make namespaces if I want to mimic crappy C++ code in the same file (assuming extern(C++, ns) just affects mangling): template _ns() { extern(C++, ns) void foo(int) {} } alias ns = _ns!(); alias foo = ns.foo; // optional template _ns2() { extern(C++, ns2) void foo(int) {} } alias ns2 = _ns2!(); alias foo = ns2.foo; // optional void main() { // foo(1); // ERROR! ns.foo(1); // OK ns2.foo(1); // OK } Why can't we just tell C++ devs who have this horrible situation to do it this way, and leave all the reasonably named namespaces to use the awesome D module system as expected? -Steve
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Saturday, 4 August 2018 at 07:34:49 UTC, Manu wrote: On Fri, 3 Aug 2018 at 18:50, Laeeth Isharc via Digitalmars-d wrote: On Friday, 3 August 2018 at 22:55:51 UTC, Rubn wrote: > > The difference is they would have to rework their existing > code. If you are writing D source code bindings for your > code, then you are essentially writing new code. You don't > have to worry about backwards compatibility. Why would you write bindings if the computer can do it for you, better, faster and consistently? Faster and consistently, sure. But I don't think 'better' is possible. From my experience, in many cases, C++ really doesn't express well in D by direct translation. I tend to do significant massaging of the C++ helper material to improve the experience from D. Usually C++ libs have a lot of helper material in the form of macros, little template utilities, inline wrappers, and they can almost always be expressed more nicely in D with some tweaking. I often also insert some additional inline D helpers/wrappers nearby the externs, which help adapt the signatures; ie, apply some attributes, or make a slice-based API that transforms to ptr+len args, maybe implement a range helper, that sort of thing. The goal is to make the API attractive such that a user is compelled to prefer interacting with the lib from D than from C++. C++ namespaces interfere with overload resolution in particular, and that makes this goal harder. It probably depends on your use. If you're just calling a C++ lib, and wrap it up in a box for use in your local code, a machine translation for the API might be fine. I'd call that 'making use of a feature lib'. If you are linking to a lib that is a fundamental part of your application infrastructure, you absolutely must do significant manual work to make the C++ code express nicely to D, otherwise the user-experience interacting with the C++ api from D will be worse than just using C++. If the C++ experience is better than from D, then D experience ceases to exist as no case can be made to prefer D over C++, the project is moot, and I have wasted my time. The D experience must not just be equal to the C++ experience, it must typically be substantially better in a variety of ways, and I have never been able to have such an experience interacting with C++ without making some manual effort towards quality bindings. The current namespace mechanics put SOOO much more strain on that goal than is necessary. One other important feature of quality bindings, is that the binding itself must be readable and maintainable. The binding itself is the very first showcase to C++ programmers of how their API's could be better in D. It must be well organised (like normal D code), and the current situation with boilerplate invading the works is destructive toward that end. Of course, thanks to this namespace situation, when involving with these hideous workarounds, they are usually objectively NOT better in D, and C++ programmers do indeed recognise that immediately. Would it be inaccurate to make a distinction between bindings and wrappers ? It's always going to be less pleasant to call even C bindings from D then an idiomatic D wrapper written on top. But if you have automatically generated bindings then you can put the effort into the wrappers and it's easier to do the latter incrementally. And being able to use a library at all even if slightly unpleasantly without having to pay a big price up front beats having no choice. At least for us the sequencing of cost matters more than the total cost, and the calendar time element of cost to being able to write a passable and useful first version is more important than the pecuniary element. We have many more people who are not C++ programmers but express their ideas in D then we do people who know C++ pretty well. BTW I almost think the D Foundation should organise a library wrapping as a service marketplace ;). Lots of people in the community are open to remote work part or full time. But the cost is in finding the right people and also to some extent supervising and organising the design and work. That could be just another forum in the beginning.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Wed, 1 Aug 2018 at 16:05, Walter Bright via Digitalmars-d 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. > > Now, with D: > > extern (C++, ab) void foo(long); > foo(0);// works! > --- > extern (C++, ab) void foo(long); > extern (C++, ab) void foo(int); // error! > --- > extern (C++, ab) void foo(long); > extern (C++, cd) void foo(int); > foo(0);// error! > > I juxtaposed the lines so it's obvious. It's not so obvious when there's a > thousand lines of code between each of those lines. It's even worse when > foo(long) sends a birthday card to your daughter, and foo(int) launches > nuclear > missiles. > > Yes, this extra protection comes at a cost - you'll have to type a bit more. > Just like D doesn't allow implicit declaration of variables, requires static > typing, and variables are always initialized unless you explicitly use `= > void`. > The protection is worth it, and is part of D's philosophy. > > I hope that adequately answers the "for some reason" :-) I'm sorry, that doesn't come remotely close justifying the imbalance. Firstly, it remains entirely hypothetical, whereas our criticisms are evidence based, over more than half a decade. "D modules do not a 1:1 correspondence with C++ namespaces, either (not even close)." - exactly. So don't even try to emulate C++'s broken feature in D. We can't win; equivalent semantics are impossible, we only get the *worst* of both worlds by trying. "Reorganizing the code into modules means potentially forcing users to split code from one C++ file into multiple D files" - Yes, that is what people do when binding C++ code. We're not writing C++ code, we're writing D code, intended to be consumed by other D code, playing by D's rules. We just want to be able to call functions that are in some C++ .obj file, and get on with writing our D code. To make a C++ API comfortable and natural to a D user, in all but the simplest cases, it has required such human intervention in all meaningful case I've attempted so far, if you want a quality result. I'm not interested in mediocre results; that does nothing but damage the impression D makes on C++ users, and thereby wasting my time and effort, and undermining the potential advance of D to a target group of interested new users. "So while Manu is clearly happy with cutting up a C++ file into multiple D files, I doubt that is universal" - support this claim? I'm happy with doing what is necessary to make a C++ API express as naturally as possible to D code. I would expect most people making such an effort to feel the same way. Why would you suspect otherwise? But then also take that in conjunction with the fact that I haven't actually argued for the demolition of the C++ namespace scope (I don't care either way). It can stay and resolve these hypotheticals if you must, although my bias is that the namespace should be applicable by some other opt-in mechanism. But I'm not interested in pushing that, I have no horse in that race. You can keep your namespace. But don't ruin C++ interaction for the rest of us! "How's that really going to
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Fri, 3 Aug 2018 at 18:50, Laeeth Isharc via Digitalmars-d wrote: > > On Friday, 3 August 2018 at 22:55:51 UTC, Rubn wrote: > > > > The difference is they would have to rework their existing > > code. If you are writing D source code bindings for your code, > > then you are essentially writing new code. You don't have to > > worry about backwards compatibility. > > Why would you write bindings if the computer can do it for you, > better, faster and consistently? Faster and consistently, sure. But I don't think 'better' is possible. >From my experience, in many cases, C++ really doesn't express well in D by direct translation. I tend to do significant massaging of the C++ helper material to improve the experience from D. Usually C++ libs have a lot of helper material in the form of macros, little template utilities, inline wrappers, and they can almost always be expressed more nicely in D with some tweaking. I often also insert some additional inline D helpers/wrappers nearby the externs, which help adapt the signatures; ie, apply some attributes, or make a slice-based API that transforms to ptr+len args, maybe implement a range helper, that sort of thing. The goal is to make the API attractive such that a user is compelled to prefer interacting with the lib from D than from C++. C++ namespaces interfere with overload resolution in particular, and that makes this goal harder. It probably depends on your use. If you're just calling a C++ lib, and wrap it up in a box for use in your local code, a machine translation for the API might be fine. I'd call that 'making use of a feature lib'. If you are linking to a lib that is a fundamental part of your application infrastructure, you absolutely must do significant manual work to make the C++ code express nicely to D, otherwise the user-experience interacting with the C++ api from D will be worse than just using C++. If the C++ experience is better than from D, then D experience ceases to exist as no case can be made to prefer D over C++, the project is moot, and I have wasted my time. The D experience must not just be equal to the C++ experience, it must typically be substantially better in a variety of ways, and I have never been able to have such an experience interacting with C++ without making some manual effort towards quality bindings. The current namespace mechanics put SOOO much more strain on that goal than is necessary. One other important feature of quality bindings, is that the binding itself must be readable and maintainable. The binding itself is the very first showcase to C++ programmers of how their API's could be better in D. It must be well organised (like normal D code), and the current situation with boilerplate invading the works is destructive toward that end. Of course, thanks to this namespace situation, when involving with these hideous workarounds, they are usually objectively NOT better in D, and C++ programmers do indeed recognise that immediately.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Friday, 3 August 2018 at 22:55:51 UTC, Rubn wrote: The difference is they would have to rework their existing code. If you are writing D source code bindings for your code, then you are essentially writing new code. You don't have to worry about backwards compatibility. Why would you write bindings if the computer can do it for you, better, faster and consistently? That's the idea behind DPP. You can just #include C headers and they will be translated before compile time. This is very helpful with projects like HDF5 that consider it acceptable in a minor release to replace a function with a macro. Wrappers are a bit different. In time C++ will follow. Not only that, who do you think even writes bindings for libraries? Most bindings are done by the community for libraries to other languages. How many companies do you know have bindings for their C/C++ libraries for D, that maintains them? We do for a few things - for other peoples' libraries not our own. But it would be better not to have to write bindings at all. damn hell no. That's what modules are for. So why are you trying to implement namespaces in D under the guise of C++ name mangling. I don't think either Manu or Atila want to be able to sneak in namespaces by the backdoor. They just want to be able easily to control namespace mangling of C++ linkage symbols. What extern(C++) should be used for is allowing you to call C++ code from D, not to be able to format C++ code into D. The only problem you have with breaking code up into multiple files is that it isn't 1:1. That's not a technical problem, it's a problem of conflicting personal opinion. If it's not 1:1, who cares? If some some odd reason you have two namespaces in one file in C++, odds are they are probably separated in that one file anyway. If not and for some reason the the code has multiple namespace definitions smashed together into one file, flip-floping between namespaces. That's not D's problem to fix the project's poor organization method. For automatically translated bindings I think that the request is not unreasonable because there's considerable value in being able to just #include C++ headers as you can already with C headers and just call the C++ code from D. D doesn't have libraries? Well it's got 1500 on code.dlang.org plus C and C++ libraries. What is it you think is missing? That's a good retort! I understand from Atila present choice just makes it a lot more complicated, not impossible.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Friday, 3 August 2018 at 21:20:37 UTC, Walter Bright wrote: On 8/2/2018 2:26 AM, Daniel N wrote: Personally I would never *bind* to two different namespaces in a single file, You'd be amazed at what people do and then set their entire store based on it. If the language spec allows it, people will do it. People will even design their code to require certain bugs in the compiler. (This really blows when you're trying to write a standard compliant C/C++ compiler and you get angry letters from customers about why I'm not supporting some stupid bug in BrandX C++ that they rely on.) One of my favorite stories about this was a company that had a coding style where their comments looked like this: // text \\ int x; They thought it was marvelous! But what really happens when you've got two line concatenation characters at the end? Is one line concatenated, or two? You have to carefully read the spec to determine which, and it matters because if two are concatenated then the declaration of x vanishes. And BrandX did it wrong, the customer wrote all their code this way, and it all broke with my compiler, and of course it was all my fault. I thought "who in their right mind would write code that way?" At least I could justify myself with BrandX is a buggy compiler, but when the behavior is in the spec, I have no leg to stand on. A simple regex could have fixed that problem. They dug themselves a hole and if they don't want to support other compiles, then they will be stuck with BrandX. If we want to support interfacing with C++, we have to support badly written C++, because that is the NORMAL case. Telling them their code is and that they should rewrite it in order to work with D is never, ever going to work. There seems to be a misunderstanding here, you don't have to rewrite the C++ code. Merely the D code has to be formatted differently. Unless you have some obsession with maintaining 1:1 C++ and D code. Which is not a technical problem, but one of organization. D isn't C++ and trying to do something crazy like make it compatible so that the files are 1:1 is crazy and unachievable. It only causes problems like what we have now. Maintaining a 1:1 correlation isn't on most D users that work with C++ wish list. Hell all of the Derelict libraries don't maintain a 1:1 at all. Another anecdote - Microsoft MASM in the 80's was full of bugs. I mean full of bugs. When Borland came out with an assembler, it wouldn't work with most of the ASM files out there. They finally had to engineer in what they called "quirks mode" to emulate MASM's bugs. Telling customers to rework their ASM files didn't work for a large company, either. The difference is they would have to rework their existing code. If you are writing D source code bindings for your code, then you are essentially writing new code. You don't have to worry about backwards compatibility. Not only that, who do you think even writes bindings for libraries? Most bindings are done by the community for libraries to other languages. How many companies do you know have bindings for their C/C++ libraries for D, that maintains them? 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. Yes. But then you'll have the people who want a 1:1 correspondence with their C++ files and the corresponding D files. I happen to be one of those people, for the ease of maintaining a translation (and for comparing it with the original C++ source code if it is not behaving correctly). Besides, I provided solutions for both Manu's case and Atila's (they are different), which are easier than "simply" breaking things up into multiple files. So why can't you define the same namespace twice in the same module? There was some conflict that didn't allow it to be implemented the same way as in C++ or something right. So why try to imitate C++ in D but fail to do so because D isn't C++. I think it's worse to try to imitate namespaces in D then create these exceptions to rules when you get snagged on a limitation. Imagine someone tried to write a DIP to add namespaces into D. Do you think anything like that would ever be accepted? God damn hell no. That's what modules are for. So why are you trying to implement namespaces in D under the guise of C++ name mangling. What extern(C++) should be used for is allowing you to call C++ code from D, not to be able to format C++ code into D. The only problem you have with breaking code up into multiple files is that it isn't 1:1. That's not a technical problem, it's a problem of conflicting personal opinion. If it's not 1:1, who cares? If some some odd reason you have two namespaces in one file in C++, odds are they are probably separated in that one file anyway. If not and for some reason the the code has multiple namespace definitions smashed
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 8/3/2018 3:58 AM, Atila Neves wrote: With your mixin template technique everything ends up in the global namespace of the moduel making the C++ declarations. Right, but that's what you wanted! I would only be able to alias a nested namespace once, since the code below obviously won't work: mixin CppNamespace0!() x; alias chrono = x.std.chrono; mixin CppNamespace1!() y; alias chrono = y.std.chrono; Try this: mixin template X() { // boilerplate prefix extern (C++, std) extern(C++, chrono) int foo(); // original line } mixin X!() x; alias foo = x.std.chrono.foo; // boilerplate suffix I considered for a while whether or not this would be truly bad, and the more I think about it the more convinced I am that Manu is right and there should be _no_ scoping whatsoever in D regarding C++ namespaces. We have packages and modules, we can use those to put the C++ functions we declare in whatever hierarchy we want. I am puzzled. With: namespace std { namespace chrono { void foo(); } } namespace std { namespace chrono { void bar(); } } you have stated that it is impractical for your translator to rewrite this as: namespace std { namespace chrono { void foo(); void bar(); } } Ok, I get that. But it is practical to rewrite it as: module std.chrono; void foo(); void bar(); ? > I mean `std` should never be part of the fully qualified name of, for > instance, `core.stdcpp.exception.std.bad_exception`. It should just > be `core.stdcpp.exception.bad_exception` instead. C++ recognizes that, too, which is why it has "using" declarations. D has the equivalent thing, "alias". You can do things like: import std = core.stdcpp.exception; and then refer to: std.bad_exception or: import exception = core.stdcpp.exception; exception.bad_exception; or whatever works best for one's project. Aliasing and import renaming (which are really just more aliasing) is very capable, and was designed for just these sorts of issues.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 8/2/2018 2:26 AM, Daniel N wrote: Personally I would never *bind* to two different namespaces in a single file, You'd be amazed at what people do and then set their entire store based on it. If the language spec allows it, people will do it. People will even design their code to require certain bugs in the compiler. (This really blows when you're trying to write a standard compliant C/C++ compiler and you get angry letters from customers about why I'm not supporting some stupid bug in BrandX C++ that they rely on.) One of my favorite stories about this was a company that had a coding style where their comments looked like this: // text \\ int x; They thought it was marvelous! But what really happens when you've got two line concatenation characters at the end? Is one line concatenated, or two? You have to carefully read the spec to determine which, and it matters because if two are concatenated then the declaration of x vanishes. And BrandX did it wrong, the customer wrote all their code this way, and it all broke with my compiler, and of course it was all my fault. I thought "who in their right mind would write code that way?" At least I could justify myself with BrandX is a buggy compiler, but when the behavior is in the spec, I have no leg to stand on. If we want to support interfacing with C++, we have to support badly written C++, because that is the NORMAL case. Telling them their code is and that they should rewrite it in order to work with D is never, ever going to work. Another anecdote - Microsoft MASM in the 80's was full of bugs. I mean full of bugs. When Borland came out with an assembler, it wouldn't work with most of the ASM files out there. They finally had to engineer in what they called "quirks mode" to emulate MASM's bugs. Telling customers to rework their ASM files didn't work for a large company, either. 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. Yes. But then you'll have the people who want a 1:1 correspondence with their C++ files and the corresponding D files. I happen to be one of those people, for the ease of maintaining a translation (and for comparing it with the original C++ source code if it is not behaving correctly). Besides, I provided solutions for both Manu's case and Atila's (they are different), which are easier than "simply" breaking things up into multiple files. 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'? In D it is not allowed to have multiple modules in the same file. This can become deeply entrenched in the way one thinks about programming, to the point where one cannot conceive of doing it other ways, i.e. ways that C++ allows, and that I believe are poor practice, but people do anyway. You can see this in the C++ backend. It is certainly not organized in a module-like manner. (It predates C++ namespaces, so doesn't use them.)
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Friday, 27 July 2018 at 23:15:44 UTC, Laeeth Isharc wrote: Because it's getting in the way of a decent prize - to be able just to #include CPP headers and link with C++. Just wanted to +100 on this one Having this feature, and if marketed well, can be huge for D This is 10 times a bigger deal than any other thing working for D right now
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Friday, 3 August 2018 at 10:58:18 UTC, Atila Neves wrote: On Wednesday, 1 August 2018 at 23:31:57 UTC, Walter Bright wrote: [...] Good point. [...] We can also just keep the current behaviour and implement something like extern(C++, "std::chrono") in addition (as manu pointed out multiple times).
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Friday, 3 August 2018 at 10:58:18 UTC, Atila Neves wrote: I thought about it some more and managed to make it work. It's definitely a hack, but since in my case the user won't usually see the generated code anyway it's not too bad. It's far from ideal, though, because I can't alias an entire nested namespace if it's declared twice, i.e. The user will actually see it, because the full name will be in all compilation errors, debugging, reflection etc. I think that's the most annoying part. But it's great that you got it working, that's the first step. :)
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Wednesday, 1 August 2018 at 23:31:57 UTC, Walter Bright wrote: On 7/31/2018 1:47 AM, Atila Neves wrote: The only good way (I don't think the mixin template and struct solutions count) to link to any of that today would be to have one enormous D file with _everything_ in it, including nested namespaces. Why doesn't it count? The user doesn't need to write that code, the translator does. It achieves what you ask for - a declaration of foo() in the current scope, with the mangling in the C++ namespace. Good point. I thought about it some more and managed to make it work. It's definitely a hack, but since in my case the user won't usually see the generated code anyway it's not too bad. It's far from ideal, though, because I can't alias an entire nested namespace if it's declared twice, i.e. namespace std { namespace chrono { // ... } } namespace std { namespace chrono { } } With your mixin template technique everything ends up in the global namespace of the moduel making the C++ declarations. I would only be able to alias a nested namespace once, since the code below obviously won't work: mixin CppNamespace0!() x; alias chrono = x.std.chrono; mixin CppNamespace1!() y; alias chrono = y.std.chrono; I considered for a while whether or not this would be truly bad, and the more I think about it the more convinced I am that Manu is right and there should be _no_ scoping whatsoever in D regarding C++ namespaces. We have packages and modules, we can use those to put the C++ functions we declare in whatever hierarchy we want. I think that this: It's where std::exception goes -> core.stdcpp.exception In it, you'll find some extern(C++,std) declarations. The file can be imported as: import core.stdcpp.exception; or: import core.stdcpp.exception : std; shouldn't even come up, by which I mean `std` should never be part of the fully qualified name of, for instance, `core.stdcpp.exception.std.bad_exception`. It should just be `core.stdcpp.exception.bad_exception` instead. If one wants to create a `core.stdcpp.chrono`, then it's a case of putting `extern(C++, std.chrono)` in that module and mirroring the namespace hierarchy manually. I don't think the extra `std` helps in any way right now, and anyone writing C++ declarations manually has to go through all the trouble of setting up aliases. None of the warts of C++ scope contaminate D this way. Nobody will ever need to know what ADL is. D scoping and overload rules would be applied, and `extern(C++)` declarations with namespaces only mangle. It would be a breaking change. However, I'd be willing to bet real money that anybody that cares about linking to C++ would gladly see their code break because they're probably using workarounds anyway. Atila
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 03/08/2018 9:12 AM, Walter Bright wrote: 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. Because it will affect mangling only, do we have any examples of c/c++ code that appends _'s to it that is used by the D community?
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Thursday, 2 August 2018 at 04:59:52 UTC, Walter Bright wrote: On 8/1/2018 7:09 PM, Rubn wrote: On Wednesday, 1 August 2018 at 23:04:01 UTC, Walter Bright wrote: 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: You can do that today, just remove the "extern(C++, ...)" part and you have the same issue. Why should C++ with namespaces be safer than just regular D ? I don't understand, if it is such a huge gigantic problem why didn't you do anything to solve this problem in regards to D then ? 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. If you *want* them in the same scope in D, you can do that with alias. You can say the same thing in D. If you have "module ab" and "module cd", if you put the function in the wrong file, you will face this same bug. It's not a hypothetical, it's the current implementation in D, yet no one has complained or filed a bug report about it. The bug is caused by the implicit conversion from int to long. That is not, nor should it be, the purpose of C++ namespaces in D to fix.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 8/2/2018 9:58 AM, Manu wrote: 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! Why is it frustrating?
Re: Is there any good reason why C++ namespaces are "closed" in D?
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.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Thu, 2 Aug 2018 at 02:05, Walter Bright via Digitalmars-d 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.
Re: Is there any good reason why C++ namespaces are "closed" in D?
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.
Re: Is there any good reason why C++ namespaces are "closed" in D?
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.
Re: Is there any good reason why C++ namespaces are "closed" in D?
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
Re: Is there any good reason why C++ namespaces are "closed" in D?
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
Re: Is there any good reason why C++ namespaces are "closed" in D?
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.
Re: Is there any good reason why C++ namespaces are "closed" in D?
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.
Re: Is there any good reason why C++ namespaces are "closed" in D?
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'?
Re: Is there any good reason why C++ namespaces are "closed" in D?
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).
Re: Is there any good reason why C++ namespaces are "closed" in D?
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?
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 8/1/2018 11:08 PM, Manu wrote: I think implementing the string alternative is the only robust way forward, because that also solves the additional problem of being able to name C++ namespaces that are invalid D keywords, which has bitten me in at least 2 particularly noteworthy occasions. Which keywords were those? In any case, this is a general problem when dealing with C and C++ interoperability, and your solution would only deal with one case of it. For example, --- C++ --- void with(); int scope; enum pure; --- 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".
Re: Is there any good reason why C++ namespaces are "closed" in D?
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.
Re: Is there any good reason why C++ namespaces are "closed" in D?
Am Wed, 01 Aug 2018 22:13:05 -0700 schrieb Walter Bright: > On 8/1/2018 12:01 PM, Manu wrote: >> You've never justified the design complexity and the baggage it >> carries. > Don't confuse you not agreeing with it with I never justified it. > > And please don't confuse me not listening to you with me not agreeing > with you. > > It *is* possible for reasonable people to disagree, especially when any > solution will involve many tradeoffs and compromises. In your most recent posts you provided some rationale for this, but nowhere as much as would have been necessary if anybody else proposed this feature and had to write a DIP for it. Introducing c++ namespace scopes added quite some complexity to the language and so far, you seem to be the only proponent of this, whereas we have many opponents. In the DIP process, such a change would have required quite a solid justification, examples, comparison to alternative solutions etc. Such a detailed rationale has never been given for this feature. -- Johannes
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Wed, 1 Aug 2018 at 22:15, Walter Bright via Digitalmars-d wrote: > > On 8/1/2018 12:01 PM, Manu wrote: > > You've never justified the design > > complexity and the baggage it carries. > Don't confuse you not agreeing with it with I never justified it. > > And please don't confuse me not listening to you with me not agreeing with > you. > > It *is* possible for reasonable people to disagree, especially when any > solution > will involve many tradeoffs and compromises. We have demonstrated consistent ongoing issues and frustration for 6 years. Your counter-argument is hypothetical at best, and has never demonstrated an advantage. Can you agree on that? I don't think that's a subjective quantity where reasonable people may disagree. If the namespace is useful in a minor subset of cases in the way you argue, then it should be a secondary feature which can be deployed independently as appropriate. It should not be conflated into a basic mangling request which we can't opt-out of. We are yet to observe a case where it was useful, and we have to do ongoing work to try and un-do the effect on our code. I also want to stress, I'm not trying to change the existing code. I'm not for a breaking change. I think implementing the string alternative is the only robust way forward, because that also solves the additional problem of being able to name C++ namespaces that are invalid D keywords, which has bitten me in at least 2 particularly noteworthy occasions. Your hypothetical scenario may continue to be served if you like.
Re: Is there any good reason why C++ namespaces are "closed" in D?
Am Wed, 01 Aug 2018 16:04:01 -0700 schrieb Walter Bright: > > Now, with D: > > extern (C++, ab) void foo(long); > foo(0);// works! > --- > extern (C++, ab) void foo(long); > extern (C++, ab) void foo(int); // error! > --- > extern (C++, ab) void foo(long); > extern (C++, cd) void foo(int); > foo(0);// error! > > I juxtaposed the lines so it's obvious. It's not so obvious when there's > a thousand lines of code between each of those lines. It's even worse > when foo(long) sends a birthday card to your daughter, and foo(int) > launches nuclear missiles. You probably didn't completely think this through: Earlier you suggested to use aliases to avoid explicitly specifying the c++ scopes. Then you suggested to use mixins or translator tools to automate alias generation and avoiding manually writing that boiler plate code. But if you do that: - extern (C++, ab) void foo(long); extern (C++, cd) void foo(int); alias foo = ab.foo; alias foo = cd.foo; - You've now got exactly the same problem with hijacking... So the benefit of explicit c++ namespace scoping is only a benefit if you do not use this alias trick. But then you face all other problems mentioned earlier... As a result, everybody now has to use the aliasing trick, the hijacking problem still exists and we have to write lots of useless boilerplate. -- Johannes
Re: Is there any good reason why C++ namespaces are "closed" in D?
Am Wed, 01 Aug 2018 16:04:01 -0700 schrieb Walter Bright: >> 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. Why would that not work with a translation tool? Just establish a fixed C+ + namespace / D module mapping, then whenever processing something in a C+ + namespace append the declaration to the corresponding 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. > > Now, with D: > > extern (C++, ab) void foo(long); > foo(0);// works! > --- > extern (C++, ab) void foo(long); > extern (C++, ab) void foo(int); // error! > --- > extern (C++, ab) void foo(long); > extern (C++, cd) void foo(int); > foo(0);// error! > > I juxtaposed the lines so it's obvious. It's not so obvious when there's > a thousand lines of code between each of those lines. It's even worse > when foo(long) sends a birthday card to your daughter, and foo(int) > launches nuclear missiles. If you insist on using a 'translator' tool anyway, it's trivial to detect this problem automatically in such a tool. -- Johannes
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 8/1/2018 12:01 PM, Manu wrote: You've never justified the design complexity and the baggage it carries. Don't confuse you not agreeing with it with I never justified it. And please don't confuse me not listening to you with me not agreeing with you. It *is* possible for reasonable people to disagree, especially when any solution will involve many tradeoffs and compromises.
Re: Is there any good reason why C++ namespaces are "closed" in D?
Am Wed, 01 Aug 2018 16:31:57 -0700 schrieb Walter Bright: > On 7/31/2018 1:47 AM, Atila Neves wrote: >> The only good way (I don't think the mixin template and struct >> solutions count) >> to link to any of that today would be to have one enormous D file with >> _everything_ in it, including nested namespaces. > > Why doesn't it count? The user doesn't need to write that code, the > translator does. I remember a time when people here were joking about all the boilerplate you have to write when using java and that it's only usable with an IDE. Now we've got a C++ interfacing which requires lots of boilerplate and is only usable with an external translater tool... 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. It's great that we can workaround the scoping with lots of boilerplate, but when is C++ namespaces introducing a scope in D actually useful? Can you give an example where this scoping is necessary? So far I have not seen a single person happily using that scoping feature. -- Johannes
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 8/1/2018 7:09 PM, Rubn wrote: On Wednesday, 1 August 2018 at 23:04:01 UTC, Walter Bright wrote: 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: You can do that today, just remove the "extern(C++, ...)" part and you have the same issue. Why should C++ with namespaces be safer than just regular D ? I don't understand, if it is such a huge gigantic problem why didn't you do anything to solve this problem in regards to D then ? 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. If you *want* them in the same scope in D, you can do that with alias.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Wednesday, 1 August 2018 at 23:04:01 UTC, Walter Bright wrote: 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: You can do that today, just remove the "extern(C++, ...)" part and you have the same issue. Why should C++ with namespaces be safer than just regular D ? I don't understand, if it is such a huge gigantic problem why didn't you do anything to solve this problem in regards to D then ?
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 7/31/2018 1:47 AM, Atila Neves wrote: The only good way (I don't think the mixin template and struct solutions count) to link to any of that today would be to have one enormous D file with _everything_ in it, including nested namespaces. Why doesn't it count? The user doesn't need to write that code, the translator does. It achieves what you ask for - a declaration of foo() in the current scope, with the mangling in the C++ namespace. All it requires from the translator is putting a boilerplate prefix and suffix onto what it already does. I.e., extern (C++, ns) int foo(); becomes: mixin template X() { // boilerplate prefix extern (C++, ns) int foo(); // original line } mixin X!() x; alias foo = x.ns.foo; // boilerplate suffix Of course, you'd also need to write X and x as X with __LINE__ appended so unique symbols are generated. (I know you've had trouble with generating unique names in another post, but that's an independent problem we should find a way to fix. Maybe instead of __LINE__, use a checksum of the original line?)
Re: Is there any good reason why C++ namespaces are "closed" in D?
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. Now, with D: extern (C++, ab) void foo(long); foo(0);// works! --- extern (C++, ab) void foo(long); extern (C++, ab) void foo(int); // error! --- extern (C++, ab) void foo(long); extern (C++, cd) void foo(int); foo(0);// error! I juxtaposed the lines so it's obvious. It's not so obvious when there's a thousand lines of code between each of those lines. It's even worse when foo(long) sends a birthday card to your daughter, and foo(int) launches nuclear missiles. Yes, this extra protection comes at a cost - you'll have to type a bit more. Just like D doesn't allow implicit declaration of variables, requires static typing, and variables are always initialized unless you explicitly use `= void`. The protection is worth it, and is part of D's philosophy. I hope that adequately answers the "for some reason" :-)
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Wed, 1 Aug 2018 at 03:05, Walter Bright via Digitalmars-d wrote: > > > Was that a deliberate > > strategy? I feel like that strategy's been used before. > > You repeatedly impugn my motives and/or my mental stability. While that > doesn't > bother me, it really does not help your case. I'm not quite sure this is a fair connection... or certainly that's not my intent. But I do struggle to understand how our arguments about the pointlessness of this complexity are so easy to dismiss, without providing any substance at all, ever, in support of the design as is. I can't accept workarounds involving manual intervention when the problem shouldn't exist in the first place. This is busy-work which we will continue to do ad-infinitum, and every time it occurs I just get more upset and unreasonable. > Please just stick to the technical issue. That ball's in your court. You've never justified the design complexity and the baggage it carries. I've prompted such justification maybe 5 times in this thread already. This isn't a technical debate. It never has been. If it was, we would have arrived at "C++ namespaces are just for mangling" 6 years ago. The evidence can't lead to any other conclusion. > Believe it or not, I really want to help you (and Laeeth and Atila) be > successful with this. Then listen to us. There's a blindingly obvious and ultimately simplifying solution. It will literally resolve _every single case_ of issue or friction or complaint i'm aware of that that has ever emerged regarding C++ namespace mangling. It has never demonstrated to be useful, and we have never identified a single issue that would be created in the process. This entire class of problem will instantly disappear. And it's not even a breaking change (ie, allow string, and then we can even solve the additional problem where we can't refer to D reserved names/keywords). Unless there are actually technical reasons to wear this complexity, recommendations including "use alias everywhere", or "put everything in one file" will never satisfy.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Wed, 1 Aug 2018 at 10:25, Jonathan M Davis via Digitalmars-d wrote: > > On Wednesday, August 1, 2018 4:02:39 AM MDT Walter Bright via Digitalmars-d > wrote: > > On 7/31/2018 1:12 AM, Manu wrote: > > > Given your favourite example: > > > > > > module a; > > > extern(C++, ns) void foo(); > > > > > > module b; > > > extern(C++, ns) void foo(); > > > - > > > module c; > > > import a, b; > > > foo(); // error: ambiguous > > > ns.foo(); // error, ambiguous (obviously) > > > a.ns.foo(); // naturally, this works... it's the D module that > > > correctly organises the symbol. 'ns' is worthless here > > > > You can write it like this: > > > > > > module a; > > extern(C++, ns) void foo(); > > alias foo = ns.foo; > > > > module b; > > extern(C++, ns) void foo(); > > alias foo = ns.foo; > > - > > > > import a,b; > > a.foo(); // calls a.ns.foo() > > b.foo(); // calls b.ns.foo() > > 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. If the namespace were just part of the mangling, none of those > aliases would be necessary. All in all, it just seems like having the > namespaces add scoping just gets in the way - especially when they would > normally get the necessary scoping from being put into separate D modules. > > Reading through this thread, and thinking about the issue, I don't see any > advantage to the current behavior over having it just affect mangling other > than the fact that that's how it currently works. All of the potential > complaints that you talk about seem like they at least _should_ be a > non-issue given that folks don't complain that way about D's module system > for non-C++ functions - but it's certainly true that even engineers aren't > always logical or reasonable. > > However, if we were discussing a DIP for implementing namespaces for C++, > based on my current understanding of the matter, I'd definitely argue that > extern(C++) with namespaces should just affect mangling, since that approach > seems much more straightforward and much more in line with how other > languages are handled, particularly since the scoping aspect is already > going to be handled by D's module system anyway. As it stands, it just seems > like the language is forcing that all C++ functions be put inside of structs > to namespace them on top of them being put into a module. And that's > downright awkward, even if it can work. Certainly, it does come across like > you didn't trust the D module system to do its job for some reason. Thank you Jonathan.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Wednesday, August 1, 2018 4:02:39 AM MDT Walter Bright via Digitalmars-d wrote: > On 7/31/2018 1:12 AM, Manu wrote: > > Given your favourite example: > > > > module a; > > extern(C++, ns) void foo(); > > > > module b; > > extern(C++, ns) void foo(); > > - > > module c; > > import a, b; > > foo(); // error: ambiguous > > ns.foo(); // error, ambiguous (obviously) > > a.ns.foo(); // naturally, this works... it's the D module that > > correctly organises the symbol. 'ns' is worthless here > > You can write it like this: > > > module a; > extern(C++, ns) void foo(); > alias foo = ns.foo; > > module b; > extern(C++, ns) void foo(); > alias foo = ns.foo; > - > > import a,b; > a.foo(); // calls a.ns.foo() > b.foo(); // calls b.ns.foo() 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. If the namespace were just part of the mangling, none of those aliases would be necessary. All in all, it just seems like having the namespaces add scoping just gets in the way - especially when they would normally get the necessary scoping from being put into separate D modules. Reading through this thread, and thinking about the issue, I don't see any advantage to the current behavior over having it just affect mangling other than the fact that that's how it currently works. All of the potential complaints that you talk about seem like they at least _should_ be a non-issue given that folks don't complain that way about D's module system for non-C++ functions - but it's certainly true that even engineers aren't always logical or reasonable. However, if we were discussing a DIP for implementing namespaces for C++, based on my current understanding of the matter, I'd definitely argue that extern(C++) with namespaces should just affect mangling, since that approach seems much more straightforward and much more in line with how other languages are handled, particularly since the scoping aspect is already going to be handled by D's module system anyway. As it stands, it just seems like the language is forcing that all C++ functions be put inside of structs to namespace them on top of them being put into a module. And that's downright awkward, even if it can work. Certainly, it does come across like you didn't trust the D module system to do its job for some reason. - Jonathan M Davis
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Wed, 1 Aug 2018 at 02:10, Walter Bright via Digitalmars-d wrote: > > On 7/31/2018 3:34 PM, Laeeth Isharc wrote: > > On Saturday, 28 July 2018 at 01:03:10 UTC, Walter Bright wrote: > >> On 7/27/2018 4:15 PM, Laeeth Isharc wrote: > >>> Can you think of a pragmatic solution to Atila's problem? > >> > >> One way is for the C++ => D translator to gather all the members of a > >> namespace before trying to emit them. Since D does not impose an order on > >> declarations (unlike C++) it is not constrained to follow the same order. > > > > So a new post preprocessor stage that parses the produced D code and > > regroups to > > group the declarations in the same namespace together ? Using DMD as a > > library > > or libdparse or something? > > I don't know how Atila's translator works. > > The htod one that I wrote would read and do the semantic processing on the > entire file before walking the data structures and emitting the corresponding > D > code, so grouping the namespace declarations would be trivial. In fact, due to > the nature of semantic processing, they would already be grouped together. None of this nuisance for Atila is necessary. You're just making busy-work for him at someone else's expense. Justify the design, and why it's worth the material cost to the users.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 7/31/2018 1:12 AM, Manu wrote: Given your favourite example: module a; extern(C++, ns) void foo(); module b; extern(C++, ns) void foo(); - module c; import a, b; foo(); // error: ambiguous ns.foo(); // error, ambiguous (obviously) a.ns.foo(); // naturally, this works... it's the D module that correctly organises the symbol. 'ns' is worthless here You can write it like this: module a; extern(C++, ns) void foo(); alias foo = ns.foo; module b; extern(C++, ns) void foo(); alias foo = ns.foo; - import a,b; a.foo(); // calls a.ns.foo() b.foo(); // calls b.ns.foo() When a C++ namespace spans modules (ie, the C++ namespace encloses the whole library's api), translation to D looks like this: module ns.submodule; extern(C++, ns) void foo(); The name is: ns.submodule.ns.foo(); // <- ns is already present at the head of the qualified name, there's no point repeating it. So don't repeat it. There is no particular reason to use that naming convention for an ns namespace. As I wrote to Atila, using 'std' as a package name isn't going to work very well anyway because it's already used as a root package in Phobos. The converse case where modules are divided by their namespace (which naturally maps to D modules): module cpplib.ns; extern(C++, ns) void foo(); Now the name is: cpplib.ns.ns.foo(); // <- why would anyone want that? Why indeed. Don't do that. I don't see any reason to. We've put things like string.h in core.stdc.string, and nobody has complained they cannot just type "import string;". It works fine. Allow me to refer to: https://github.com/dlang/druntime/blob/master/src/core/stdcpp/exception.d It's where std::exception goes -> core.stdcpp.exception In it, you'll find some extern(C++,std) declarations. The file can be imported as: import core.stdcpp.exception; or: import core.stdcpp.exception : std; or any of a number of other ways to import it and set up aliases (if one prefers) to use as shortcuts to the name. But the redundancy is more than a nuisance in certain forms of scanning meta. As I mentioned, you can use alias to refer to names in other scopes. And got forbid the case where C++ namespaces are embedded (namespace for lib name, another for the module), and we have this: module lib_ns.module_ns; extrern(C++, lib_ns) extern(C++, module_ns) void foo(); The name is: lib_ns.module_ns.lib_ns.module_ns.foo(); // <- words can't even I have no idea why it would be necessary to write such. I suspect you are unfamiliar with the uses of 'alias' to refer from one scope to names in another. Was that a deliberate strategy? I feel like that strategy's been used before. You repeatedly impugn my motives and/or my mental stability. While that doesn't bother me, it really does not help your case. Please just stick to the technical issue. Believe it or not, I really want to help you (and Laeeth and Atila) be successful with this.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 7/31/2018 1:43 AM, Atila Neves wrote: It's not the same - if I want to link to std::vector and std::string, I'd expect them to be used in D as std.vector and std.string, not std.vector and HackyDThing0.std.string. Calling them std.string will already cause problems, because there's an std.string in Phobos. You could call it core.stdcpp.string, analogously to core.stdc.string for string.h. Keep in mind that with 'alias' names can behave as if they are moved to another scope.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 7/31/2018 3:34 PM, Laeeth Isharc wrote: On Saturday, 28 July 2018 at 01:03:10 UTC, Walter Bright wrote: On 7/27/2018 4:15 PM, Laeeth Isharc wrote: Can you think of a pragmatic solution to Atila's problem? One way is for the C++ => D translator to gather all the members of a namespace before trying to emit them. Since D does not impose an order on declarations (unlike C++) it is not constrained to follow the same order. So a new post preprocessor stage that parses the produced D code and regroups to group the declarations in the same namespace together ? Using DMD as a library or libdparse or something? I don't know how Atila's translator works. The htod one that I wrote would read and do the semantic processing on the entire file before walking the data structures and emitting the corresponding D code, so grouping the namespace declarations would be trivial. In fact, due to the nature of semantic processing, they would already be grouped together.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Tuesday, 31 July 2018 at 23:02:16 UTC, Rubn wrote: One thing I don't like is that the C++ namespaces takes the name. So if you try to import a module that has C++ namespace of the same with the existing module, then you'll get an error. For effectively no reason, because as you say that namespace is useless and just occupies a name that could otherwise be used for the module name. Indeed, case in point: std
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Tuesday, 31 July 2018 at 16:23:55 UTC, Manu wrote: On Tue., 31 Jul. 2018, 3:40 am Jacob Carlborg via Digitalmars-d, < digitalmars-d@puremagic.com> wrote: On 2018-07-31 10:12, Manu wrote: > Given your favourite example: > > module a; > extern(C++, ns) void foo(); > > module b; > extern(C++, ns) void foo(); > - > module c; > import a, b; > foo(); // error: ambiguous > ns.foo(); // error, ambiguous (obviously) > a.ns.foo(); // naturally, this works... it's the D module > that > correctly organises the symbol. 'ns' is worthless here This works: a.foo(); You don't need "ns" in between the module name and the function. Right... But did you miss the point? The D module does the organisation (as you show). The ns offers nothing and creates other kinds of problems. Just because name resolution traverses the namespace (in simple cases), there is an entire language of complexity that interacts with that name lookup, and as far as I know, it has never proven useful, but rather, only complicated and annoying leading to boilerplate and hacks in certain situations. (ie, this thread exists and many others) Can you give some examples of those certain situations? It would help clear what is wrong with how it is currently implemented. One thing I don't like is that the C++ namespaces takes the name. So if you try to import a module that has C++ namespace of the same with the existing module, then you'll get an error. For effectively no reason, because as you say that namespace is useless and just occupies a name that could otherwise be used for the module name.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Saturday, 28 July 2018 at 01:03:10 UTC, Walter Bright wrote: On 7/27/2018 4:15 PM, Laeeth Isharc wrote: Can you think of a pragmatic solution to Atila's problem? One way is for the C++ => D translator to gather all the members of a namespace before trying to emit them. Since D does not impose an order on declarations (unlike C++) it is not constrained to follow the same order. So a new post preprocessor stage that parses the produced D code and regroups to group the declarations in the same namespace together ? Using DMD as a library or libdparse or something?
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Tue., 31 Jul. 2018, 3:40 am Jacob Carlborg via Digitalmars-d, < digitalmars-d@puremagic.com> wrote: > On 2018-07-31 10:12, Manu wrote: > > > Given your favourite example: > > > > module a; > > extern(C++, ns) void foo(); > > > > module b; > > extern(C++, ns) void foo(); > > - > > module c; > > import a, b; > > foo(); // error: ambiguous > > ns.foo(); // error, ambiguous (obviously) > > a.ns.foo(); // naturally, this works... it's the D module that > > correctly organises the symbol. 'ns' is worthless here > > This works: > > a.foo(); > > You don't need "ns" in between the module name and the function. > Right... But did you miss the point? The D module does the organisation (as you show). The ns offers nothing and creates other kinds of problems. Just because name resolution traverses the namespace (in simple cases), there is an entire language of complexity that interacts with that name lookup, and as far as I know, it has never proven useful, but rather, only complicated and annoying leading to boilerplate and hacks in certain situations. (ie, this thread exists and many others)
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 2018-07-31 10:12, Manu wrote: Given your favourite example: module a; extern(C++, ns) void foo(); module b; extern(C++, ns) void foo(); - module c; import a, b; foo(); // error: ambiguous ns.foo(); // error, ambiguous (obviously) a.ns.foo(); // naturally, this works... it's the D module that correctly organises the symbol. 'ns' is worthless here This works: a.foo(); You don't need "ns" in between the module name and the function. -- /Jacob Carlborg
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Tuesday, 31 July 2018 at 08:33:52 UTC, Daniel N wrote: On Monday, 30 July 2018 at 13:48:46 UTC, Atila Neves wrote: 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") This doesn't work for templates. If it did I wouldn't have an issue since libclang tells me what the mangling is. What is the deal-breaker with templates? For simple functions libclang + pragma seems the best option right now. template fun() { pragma(mangle, "_ZN2ns3funEv") extern(C++) void fun() {} } mixin fun; extern(C++) { void foo(T)() { } } It doesn't have a mangling until it has an instantiation. Even if it were possible to know which exact instantitations the code that imports this uses, there's no way I can declare the mangling scheme to the D compiler.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Tuesday, 31 July 2018 at 08:33:52 UTC, Daniel N wrote: On Monday, 30 July 2018 at 13:48:46 UTC, Atila Neves wrote: 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") This doesn't work for templates. If it did I wouldn't have an issue since libclang tells me what the mangling is. What is the deal-breaker with templates? For simple functions libclang + pragma seems the best option right now. template fun() { pragma(mangle, "_ZN2ns3funEv") extern(C++) void fun() {} } mixin fun; Your template doesn't have any template parameter. Bear in mind mangling is dependent on the instance, not the declaration. Once you add some template parameter, you need to mangle your template parameter list, which you could *almost* reasonably do with CTFE, but since you are on POSIX, you also got fun things like components and template parameter substitution. Example: ``` struct Array16479 (Arg) { Arg* data; } Array16479!(FuncT2) func16479_4 (FuncT1, FuncT2) (FuncT1); static assert(func16479_4!(int, float).mangleof == `_Z11func16479_4IifE10Array16479IT0_ET_`); ``` As you see the return value (`Array16479IT0_E`) encode a backreference to the symbol's template parameter: T0_ reference the second template argument. If you throw some more language features (e.g. aliases) you quickly realize you need a full semantic analysis to get the mangling right on templates. More test cases/examples (and shameless self plug): https://github.com/dlang/dmd/pull/8455/files
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Monday, 30 July 2018 at 20:23:25 UTC, Walter Bright wrote: On 7/30/2018 9:45 AM, Manu wrote: Sure it 'works', but it's an annoying point of friction, and it doesn't need to be that way. You can reduce it to: mixin(cppNamespace("ns", "void foo();")); You haven't explained why you can't just move the namespace ns declarations in one file together. Are you serious? Yes, please explain why you can't coalesce the namespace declarations in one C++ file into one namespace declaration. Because one C++ file != one C++ translation unit. All of them will #include other files and need the symbols in them, which, for anything using namespaces (the standard library, boost, ...), will mean several instances of opening and closing the same namespace. The only good way (I don't think the mixin template and struct solutions count) to link to any of that today would be to have one enormous D file with _everything_ in it, including nested namespaces.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Monday, 30 July 2018 at 19:51:09 UTC, Walter Bright wrote: On 7/30/2018 6:45 AM, Atila Neves wrote: On Friday, 27 July 2018 at 22:50:20 UTC, Walter Bright wrote: On 7/27/2018 10:28 AM, Atila Neves wrote: But all I'm trying to do here is tell the D compiler how to mangle symbols. Namespaces have semantic implications, too, such as overload resolutions. A namespace introduces a new scope, not just a mangling. Should they, though? They do in C++. That was the whole point of adding namespaces: C:void ns_foo(); C++: namespace ns { void foo(); } I meant "should they in D, though?". I don't want to import C++ semantics into D. I want D to correctly mangle C++ namespaced functions and change nothing at all about overload resolution in D. Structs aren't namespaces, I wouldn't expect them to behave the same. From a language perspective, they are namespaces. Technically, yes. But not C++ namespaces. C++ has a lot of bizarre name lookup behavior. It does. I don't think anyone is suggesting we copy it. I didn't know about this and it makes things better, but it's not a real solution to my problem. See my other post doing this same thing with structs. It's not the same - if I want to link to std::vector and std::string, I'd expect them to be used in D as std.vector and std.string, not std.vector and HackyDThing0.std.string. I'm arguing that reopening should be allowed. As detailed in another post, this opens a whole host of other problems. Even in C++, what names are visible in a namespace at any particular point in the compilation is a nebulous concept. (It is actually carefully specified, but you have to be a language lawyer / compiler implementer to know what they are - to the user it is erratic, random, and nebulous.) Right, but D doesn't have to do any of that - as far as D is concerned it's just mangling. Well, as far as the typical D user that writes `extern(C++)` anyway.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Tuesday, 31 July 2018 at 06:12:40 UTC, Walter Bright wrote: Thirdly, C and C++ are loaded to the gills with seemed-like-a-good-idea-at-the-time solutions that turned out to have bad unintended consequences that bork up the language for everyone down the line. D has some of those, too. And only experience can tell if those ideas turn out to be bad, as people make use of it and realize how (im)practical they are. We only got a handful known serious users of `extern (C++)` on Windows, and probably only me on POSIX (because anything templated doesn't mangle properly on POSIX, so the STL is unusable). So if all users come together to say that the current design seemed-like-a-good-idea-at-the-time (to you) but is not, and could be *simplified* to yield a better product, it sounds very backward to not listen to them.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Monday, 30 July 2018 at 13:48:46 UTC, Atila Neves wrote: 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") This doesn't work for templates. If it did I wouldn't have an issue since libclang tells me what the mangling is. What is the deal-breaker with templates? For simple functions libclang + pragma seems the best option right now. template fun() { pragma(mangle, "_ZN2ns3funEv") extern(C++) void fun() {} } mixin fun;
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Mon, 30 Jul 2018 at 23:15, Walter Bright via Digitalmars-d wrote: > > My issue is you're presenting solutions. But I have no idea what the problem > is, > because every time I present a solution to the examples you give, you say it's > no good, because your problem is something else. I'm not asking for workarounds or 'solutions'. I know the workarounds very well, because I've been writing them repeatedly for years. I want to see this mistake corrected. It's not a case of "can't do the thing", this is a case of "i hate doing the thing (ie, workarounds), the results are particularly unsatisfying, and the whole basis for the problem is unfounded". We repeat it over and over. The case on trial today is that it can't be 'reopened', which is awkward in cases of generative programming (like Atila's case), and is a conversation that shouldn't even need to exist; a namespace given for mangling doesn't exhibit this issue. We can't specify some valid C++ namespace names that are D keywords. (also, 'std' is particularly annoying, since it conflicts with phobos) Other cases where it conflicts with itself when you import 2 modules with symbols spanning the same namespace, which is more common than not. The resolution is explicit disambiguation using the D module scope (which is the whole point of D modules), and so the C++ namespace scope is just redundant. Given your favourite example: module a; extern(C++, ns) void foo(); module b; extern(C++, ns) void foo(); - module c; import a, b; foo(); // error: ambiguous ns.foo(); // error, ambiguous (obviously) a.ns.foo(); // naturally, this works... it's the D module that correctly organises the symbol. 'ns' is worthless here Just like every other instance in D code ever where modules are used to organise symbols. I don't have to convince you that D modules work well... you need to convince us that D modules are insufficient. ns is just annoying complexity, and it interferes with other code. Atila's thing about 'reopening' namespaces is a non-issue if namespace was just for mangling. The whole class of problem ceases to exist. (I have been frustrated by this same problem too) Scanning meta doesn't have to learn to identify and recurse into C++ namespaces to traverse that edge case where a module has some C++ symbols. No scanning meta every written is equipped with that logic. There's no advantage to the ns scope, and it only brings challenges. None of any of our time ever needed to be wasted here. The feature as designed absolutely has not solved any form of problem. It has not saved more time than it's wasted, and it never will. Not to mention that it's ugly and leads to undesirable and unintuitive symbol names. When a C++ namespace spans modules (ie, the C++ namespace encloses the whole library's api), translation to D looks like this: module ns.submodule; extern(C++, ns) void foo(); The name is: ns.submodule.ns.foo(); // <- ns is already present at the head of the qualified name, there's no point repeating it. The converse case where modules are divided by their namespace (which naturally maps to D modules): module cpplib.ns; extern(C++, ns) void foo(); Now the name is: cpplib.ns.ns.foo(); // <- why would anyone want that? In both cases it's just a repeat of what's already in the module name. But the redundancy is more than a nuisance in certain forms of scanning meta. And got forbid the case where C++ namespaces are embedded (namespace for lib name, another for the module), and we have this: module lib_ns.module_ns; extrern(C++, lib_ns) extern(C++, module_ns) void foo(); The name is: lib_ns.module_ns.lib_ns.module_ns.foo(); // <- words can't even > My second point is that changing the language is a last resort solution, not a > first resort. This isn't a last-resort, this was truly a first-resort... I started making this noise within some number of hours after the appearance of the design countable on my fingers. (far less aggressively, having not spent years of my life stewing on this) You've just blocked the conversation for sufficiently long that now you're able to say that sentence you just said. Was that a deliberate strategy? I feel like that strategy's been used before. That said, I'm not proposing a language 'change', we can just support a string version in parallel and everything's fine if we don't want to deprecate the scope version. > Thirdly, C and C++ are loaded to the gills with > seemed-like-a-good-idea-at-the-time solutions that turned out to have bad > unintended consequences that bork up the language for everyone down the line. > D > has some of those, too. extern(C++, ns) is the poster child of exactly that. In this case, it seemed-like-a-good-idea to one person and was implemented with no consultation of anyone. The design was never presented or scrutinised. It just merged, and when we promptly complained, our criticism were rejected on principle. Maybe we should write up a retro-DIP, and see if it passes
Re: Is there any good reason why C++ namespaces are "closed" in D?
My issue is you're presenting solutions. But I have no idea what the problem is, because every time I present a solution to the examples you give, you say it's no good, because your problem is something else. I cannot reverse engineer what the issue is from your proposed solution. My second point is that changing the language is a last resort solution, not a first resort. Thirdly, C and C++ are loaded to the gills with seemed-like-a-good-idea-at-the-time solutions that turned out to have bad unintended consequences that bork up the language for everyone down the line. D has some of those, too. Forgive me, but: extern (C++, "ns") has a definite smell about it of something going awry, and the idea that it shouldn't introduce a scope because nobody relies on C++ namespaces being in a scope despite that being the whole point of namespaces is a giant red flag of something terribly wrong somewhere.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 7/30/2018 2:12 PM, Manu wrote: We're all happy with the D module system, that's how we want to organise our code. Please let us organise our code using the D module system. I have literally no idea what you mean. That's why I suggest you show what your C++ code looks like, and what you want to do with modules in D.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 29.07.2018 09:37, Walter Bright 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. How would that work? I don't think this is possible. 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. ... Well, they already can do this with the global scope. 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. ... Again, this does not seem possible. 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. :-) Well, for Atila, the only issue is that there cannot be two namespace declarations of the same name in the same source file. I don't think it is necessary to change scope lookup rules at all, just put declarations from namespaces with identical names into the same name space. Note that we already need to define semantics for code like this: struct ns{ static: int decl0; static if(is(typeof(reopenNS1))) mixin(reopenNS1); } int arbitrarily_many_intermediate_declarations0; enum reopenNS1=q{ int decl1; static if(is(typeof(reopenNS2))) mixin(reopenNS2); }; int arbitrarily_many_intermediate_declarations1; enum reopenNS2=q{ int decl2; static if(is(typeof(reopenNS3))) mixin(reopenNS3); }; static assert(is(typeof(ns.decl0+ns.decl1+ns.decl2))); In terms of lookup, this is a similar problem to namespaces. I think Atila could probably even emit ugly code like this to solve his original problem, but it would slow down compilation unnecessarily. There are no new lookup issues here.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Mon, 30 Jul 2018 at 13:25, Walter Bright via Digitalmars-d wrote: > > On 7/30/2018 9:45 AM, Manu wrote: > > Sure it 'works', but it's an annoying point of friction, and it > > doesn't need to be that way. > > You can reduce it to: > > mixin(cppNamespace("ns", "void foo();")); > > > >> You haven't explained why you can't just move the namespace ns > >> declarations in > >> one file together. > > > > Are you serious? > > Yes, please explain why you can't coalesce the namespace declarations in one > C++ > file into one namespace declaration. We're talking about multiple C++ files, not one. Problems arise when you import 2 modules since the namespaces collide. You need to disambiguate with the D module identifier anyway, which self-defeats the whole design! The C++ namespaces are redundant. They just lead to user confusion, and more tedious metacrobatics when scanning for things. No scanning meta supports recursing into C++ namespaces. > > When torrents of people complain, you can send every single one of > > them to me, tell me "I told you so", and I'll eat my hat. > > Apologies don't pay the bills. C++ is full of such stuff, and the bill for it > is > staggering. I'm suggesting there will not be any such bug report. The result will be simpler and more intuitive, and there will be less complaints, not more. We don't want C++'s namespaces in D. I have no idea why you do... cus you go on and on about how complex and horrible they are. And now we have a thing that's not like C++ namespaces, and also not like normal D code (where normal D modules would be absolutely fine). I agree with you completely... I don't want C++ namespaces in D. I also don't want _anything like them_. We're all happy with the D module system, that's how we want to organise our code. Please let us organise our code using the D module system.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 7/30/2018 9:45 AM, Manu wrote: Sure it 'works', but it's an annoying point of friction, and it doesn't need to be that way. You can reduce it to: mixin(cppNamespace("ns", "void foo();")); You haven't explained why you can't just move the namespace ns declarations in one file together. Are you serious? Yes, please explain why you can't coalesce the namespace declarations in one C++ file into one namespace declaration. When torrents of people complain, you can send every single one of them to me, tell me "I told you so", and I'll eat my hat. Apologies don't pay the bills. C++ is full of such stuff, and the bill for it is staggering.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 7/30/2018 6:48 AM, Atila Neves wrote: This doesn't work for templates. If it did I wouldn't have an issue since libclang tells me what the mangling is. You're right.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 7/30/2018 5:07 AM, Daniel N wrote: I tried that but it mangles wrong.. it includes "S1" which is not what you want, You're right, and I fixed that in a reply to Atila.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 7/30/2018 7:20 AM, Atila Neves wrote: -- extern (C++, ns) { int foo() { return 1; } } mixin template X() { extern (C++, ns) { int bar() { return 2; } } } mixin X!() x; --- void main() { pragma(msg, __traits(allMembers, ns)); foo; bar; } $ dmd foo.d tuple("foo") foo.d(15): Error: undefined identifier bar That method doesn't compile. You'll need to add: alias bar = x.bar; which will add bar to the current scope. foo.o:foo.d:function _Dmain: error: undefined reference to 'S::ns::bar()' Hmm, when I tested it the 'S::' prefix wasn't there. But when I retested it, it was. (!) I'll look into this.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 7/30/2018 1:05 PM, Walter Bright wrote: I'll look into this. Check this: --- extern (C++, ns) { int foo(); } mixin template X() { extern (C++, ns) int bar(); } mixin X!() x; alias bar = x.ns.bar; void main() { foo(); bar(); pragma(msg, foo.mangleof); pragma(msg, bar.mangleof); } --- dmd -c test ?foo@ns@@YAHXZ ?bar@ns@@YAHXZ
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 7/30/2018 6:45 AM, Atila Neves wrote: On Friday, 27 July 2018 at 22:50:20 UTC, Walter Bright wrote: On 7/27/2018 10:28 AM, Atila Neves wrote: But all I'm trying to do here is tell the D compiler how to mangle symbols. Namespaces have semantic implications, too, such as overload resolutions. A namespace introduces a new scope, not just a mangling. Should they, though? They do in C++. That was the whole point of adding namespaces: C:void ns_foo(); C++: namespace ns { void foo(); } Structs aren't namespaces, I wouldn't expect them to behave the same. From a language perspective, they are namespaces. doesn't. Being able to crack open a scope and stuff more symbols into it at any point in a program is just madness :-) Perhaps, but that's how C++ works. C++ has a lot of bizarre name lookup behavior. I didn't know about this and it makes things better, but it's not a real solution to my problem. See my other post doing this same thing with structs. I'm arguing that reopening should be allowed. As detailed in another post, this opens a whole host of other problems. Even in C++, what names are visible in a namespace at any particular point in the compilation is a nebulous concept. (It is actually carefully specified, but you have to be a language lawyer / compiler implementer to know what they are - to the user it is erratic, random, and nebulous.) C++ gets away with this because programmers assume the fault lies within themselves. That doesn't work for D - they assume I'm an idiot. I get the bill. I posted a solution to Manu a couple times now, to you as a user it would look like: mixin(cppNamespace("ns", "void foo();")); and can be done with D today.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 7/30/18 12:45 PM, Manu wrote: On Mon, 30 Jul 2018 at 01:45, Walter Bright via Digitalmars-d wrote: On 7/29/2018 8:05 PM, Manu wrote: ab.d -- module ab; extern(C++, "ab") void foo(); cd.d -- module cd; extern(C++, "cd") void foo(); Perfect! extern(C++, ab) void foo(); extern(C++, cd) void foo(); Perfect! struct S1 { extern(C++, ns) void foo(); } alias foo = S1.ns.foo; struct S2 { extern(C++, ns) void bar(); } alias bar = S2.ns.bar; Perfect! What is this? I don't get what you are doing here. We have what already exists, that can't go away now, but please just give us string namespaces as a mangle-only option. Not only will I shut up about it forever, but we will also be able to specify namespaces that conflict with D keywords, and also organise our modules just like all other D code ever. I'm the one that gets stuck with the fallout from bad designs. The solution I proposed above will work for you as best as I can tell. And it works right now, you don't have to wait for another version. Sure it 'works', but it's an annoying point of friction, and it doesn't need to be that way. It requires over-specification of the namespace at calls, and it creates friction for scanning meta. It offers nothing, and only makes things harder and unintuitive. Why do you have such a strong opinion about a thing that you don't use? None of the customers ever suggested it should be like it is. Just let us mangle our symbols! We'll design our modules how we like; we're not morons, we want to present API's to users in logical and sensible ways. You haven't explained why you can't just move the namespace ns declarations in one file together. Are you serious? https://github.com/dlang/druntime/pull/2259 <- There, I fixed it for you. I can't wait to get all the container classes in there too! If you really believe that, and not just trolling me, then click merge. hehe, you need to put them all into one extern(C++, std), right? Not to mention having std as an identifier is somewhat problematic in D. Why would I want to have one gigantic module with everything dumped in it? No end-user wants that. We just want to use D as it is. What is so bad about D's module system that you plainly refuse to let us use it as it was intended? Just allow a string version. It's going to be okay. Everybody will be happier. The sky won't fall. When torrents of people complain, you can send every single one of them to me, tell me "I told you so", and I'll eat my hat. While I agree with Manu that extern(C++, ns) would be better as just mangling, please don't just make the difference that it's a string literal vs. symbol. That difference is going to be confusing. Not to mention the abuse from calling CTFE functions. e.g.: string ns() { return "theNamespace"; } extern(C++, ns) or extern(C++, ns())? I'd suggest something like (shudder) extern(mangleC++, ns). None of this is attractive... Note that namespaces in D have been doable via templates or classes or structs for a long time. There is really no need to deal with C++ namespaces in D. -Steve
Re: Is there any good reason why C++ namespaces are "closed" in D?
On 7/30/2018 6:47 AM, Atila Neves wrote: As mentioned in the original post, the gathering is going to be incredibly annoying If you did it manually, sure. But altering the translator to do it? and I suspect I'll run into problems with macros. I thought you were running the preprocessor first? Besides, I mentioned a solution in a reply to Manu.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Mon, 30 Jul 2018 at 01:45, Walter Bright via Digitalmars-d wrote: > > On 7/29/2018 8:05 PM, Manu wrote: > > ab.d > > -- > > module ab; > > extern(C++, "ab") void foo(); > > > > > > cd.d > > -- > > module cd; > > extern(C++, "cd") void foo(); > > > > Perfect! > >extern(C++, ab) void foo(); >extern(C++, cd) void foo(); > > Perfect! > >struct S1 { extern(C++, ns) void foo(); } alias foo = S1.ns.foo; >struct S2 { extern(C++, ns) void bar(); } alias bar = S2.ns.bar; > > Perfect! > > > > We have what already exists, that can't go away now, but please just give us > > string namespaces as a mangle-only option. Not only will I shut up about it > > forever, but we will also be able to specify namespaces that conflict with D > > keywords, and also organise our modules just like all other D code ever. > > I'm the one that gets stuck with the fallout from bad designs. The solution I > proposed above will work for you as best as I can tell. And it works right > now, > you don't have to wait for another version. Sure it 'works', but it's an annoying point of friction, and it doesn't need to be that way. It requires over-specification of the namespace at calls, and it creates friction for scanning meta. It offers nothing, and only makes things harder and unintuitive. Why do you have such a strong opinion about a thing that you don't use? None of the customers ever suggested it should be like it is. Just let us mangle our symbols! We'll design our modules how we like; we're not morons, we want to present API's to users in logical and sensible ways. > You haven't explained why you can't just move the namespace ns declarations in > one file together. Are you serious? https://github.com/dlang/druntime/pull/2259 <- There, I fixed it for you. I can't wait to get all the container classes in there too! If you really believe that, and not just trolling me, then click merge. Why would I want to have one gigantic module with everything dumped in it? No end-user wants that. We just want to use D as it is. What is so bad about D's module system that you plainly refuse to let us use it as it was intended? Just allow a string version. It's going to be okay. Everybody will be happier. The sky won't fall. When torrents of people complain, you can send every single one of them to me, tell me "I told you so", and I'll eat my hat.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Sunday, 29 July 2018 at 07:45:35 UTC, Walter Bright wrote: 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; --- void main() { pragma(msg, __traits(allMembers, ns)); foo; bar; } $ dmd foo.d tuple("foo") foo.d(15): Error: undefined identifier bar That method doesn't compile. and another: - extern (C++, ns) { int foo(); } struct S { extern (C++, ns) { int bar(); } } void main() { foo; bar; } I changed them to be only declarations, since the goal is to call existing C++ code, not to define it in a D file. `foo` works as expected, but `bar`... foo.o:foo.d:function _Dmain: error: undefined reference to 'S::ns::bar()' collect2: error: ld returned 1 exit status Neither method works.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Saturday, 28 July 2018 at 01:03:10 UTC, Walter Bright wrote: On 7/27/2018 4:15 PM, Laeeth Isharc wrote: Can you think of a pragmatic solution to Atila's problem? One way is for the C++ => D translator to gather all the members of a namespace before trying to emit them. Since D does not impose an order on declarations (unlike C++) it is not constrained to follow the same order. As mentioned in the original post, the gathering is going to be incredibly annoying and I suspect I'll run into problems with macros.