On 3 January 2016 at 15:40, Walter Bright via Digitalmars-d < digitalmars-d@puremagic.com> wrote:
> On 1/2/2016 8:54 PM, Manu via Digitalmars-d wrote: > >> C++ namespacing is causing me endless, and I mean *endless* trouble. >> This idea that we express the C++ namespace hierarchy in D is the main >> problem. >> I don't think C++ namespaces should interfere with D scoping rules, they >> should >> be purely for mangling. >> It creates a whole bundle of edge cases which either don't have work >> arounds, or >> REALLY awkward workarounds which typically have a heavy impact on all the >> regular D code that the C++ code interacts with. >> >> Not least of which is that C++ namespaces usually span the entire >> project, and >> in D a C++ namespace can only appear in one module ever. >> Declaring symbols with the same C++ namespace in different modules leads >> to >> multiple definition errors, and if you are super-careful to avoid those, >> you >> gain name resolution issues in it's place. >> > > That works the same as in C++. Don't define the same symbol in the same > C++ namespace in multiple modules. It doesn't work in C++, and doesn't work > in D for exactly the same reason. > I'm not defining the same symbols, I'm defining different symbols, just inside the same namespace. It is also very awkward that a C++ namespace can't be the same as a top >> level >> package name. My top level package is named the same as one of my C++ >> namespaces... what do I do? It gets ugly real fast. >> >> The main problem extends from this situation: >> >> module x.y; >> >> extern(C++, ns) struct Y {} >> >> >> module ns.m; >> >> import x.y; // fail, the c++ namespace is already present (top level >> module) >> > > Doesn't fail when I try it. Import another module with the same namespace, have the objects within each instance of the namespace refer to eachother. import x.y : Y; // fail, not found >> > > Again, Y is not module scope. > > // This **sometimes** works, >> > > sometimes? Yes, it works sometimes. and it's very brittle >> > > ?? It only 'sometimes' works. Reasons are not clear. static import x.y; >> alias Y = x.y.Y; >> > > Nothing wrong with that. Except that it doesn't always work. It also implies that I must double the number of modules I have, so that I can wrap every module with a C++ namespace in an outer one without it. Thing is, I'm not declaring a C++ object, I'm declaring a D object, the >> only >> thing being that struct's take care to maintain common binary layout, and >> functions just mangle like C++ so that my code links. I'm in D, I'm >> declaring my >> stuff in the D module where it should be scoped, and where other D code >> should >> expect to find it. I don't see any point in building the C++ hierarchy in >> this >> space. C++ namespace rules are incompatible with D; you can litter them >> through >> C++ code, and add new symbols to C++ namespaces from anywhere... >> > > You can do that in D as well, as long as you follow the One Definition > Rule, which you have to with C++ code anyway. It doesn't scale though. module x.x; import x.y; extern(C++, ns) { class X { Y y; } } module x.y; import x.x; extern(C++, ns) { class Y { X x; } } Error: undefined identifier 'Y' this is >> fundamentally incompatible with D, and no further reasoning should be >> required >> to conclude that it can't be reproduced, so it should be for mangling >> purposes only. >> > > I guarantee you that if we'd implemented it that way, you'd have a long > litany of complaints about that, because the compiler could not distinguish > Y from ns.Y. You would put it in its own module like normal D code, and let normal D symbol resolution take care of it. That's surely the preferred approach anyway? Chances are, your D module structure will match the C++ module structure verbatim anyway, which will have already been structured that way. I have spent **days**, actually, weeks of my free time trying to make my >> tiny >> bit of code build, and it's just nothing but trouble after trouble. I have >> completely restructured my code at least 3 times to try and find a way to >> make >> it fit together in a way that's both practical and works, but I just >> can't. It >> always hits some brick wall somewhere. >> >> extern(C++, NS) looks okay in isolated tests/experiments, but try and >> actually >> use it, and you will become very frustrated. >> >> Please, fix this. I'm almost done. I'm really struggling to keep this >> dream alive. >> > > I do not understand what difficulty you are having with this. > It's endlessly difficult, and it's really hard to summarise. I'm telling you this; as someone who's endlessly fought with this in practical real-world applications, the design is wrong. D has module scoping, it works, let D's scoping do it's job. This design can lead to nothing but edge cases. We have plenty of edges already. There was a binary decision made; as far as I know, the decision was made on a whim, there was no design committee, a decision was simply chosen. I know of no argument that demonstrates that the current state is correct, but I have months of wasted time and energy that prove that it's wrong. Why do I need to now take even more time to construct an elaborate suite of examples to demonstrate my argument? I can't get work done. I've spent all the free time I have trying, and I'd rather write code than spend my time reducing test cases. Try and bind to a reasonably complex C++ project and you will discover the same thing... or don't, I've honestly already done that work for you! Please don't make me waste endlessly more of my time, I don't have energy left to spare. This is precisely what's driving me away from D. I can't take it anymore, everything hits brick walls, I am so frustrated, I just want to have a **SINGLE** win, where I can complete a single real-world project and say I have written something that works! If you're not convinced, then start by fixing the forward referencing issues. They are just bugs, and I highly suspect that many of my tests and experiments have been hindered by the fact that there are actually 2-3 issues working here in tandem. The error messages all look basically the same and offer no help. Forward referencing issue == "undefined identifier", namespace conflict == "undefined identifier". I suspect that cases exist where I was testing one thing, and the other thing jumped in and caused a mis-diagnosis. That doesn't mean it's not wrong though... let the D module system do what it's designed to do. The point of extern(C++) is to present a C++ API to a D user, so it needs to be arranged in D's terms or the user will feel very uncomfortable, and the author will have to jump through more hoops than if they just stuck with C++.