.. you forgot to mention also, that (in the context of a D module) D stops treating a user-defined class-type as real type. Additionally, a D class is a reference type. Whereas in C++, a class type is a real type (treated as any built-in type), and is a value type (by default).
Nor does D have a concept of C++ friend.
So even when it comes to classes, C++ and D are miles apart.
D structs are value types, D classes are reference types. This was done to avoid mistakes like having a type that is sometimes used as a value type and sometimes as a reference type.
Would have been much better in my opinion, if D had maintained a C like struct (not a C++ like struct), and a C++ like class. That would have solved the problem you identified, while still allowing for the class to be what it was designed to be. The mistake C++ made was the mistake you identified. But the solution you provided in D is its own mistake.
The C++ class would require the user to constantly remember it has to be passed by reference, not by value. D making the class a reference type means the user cannot mix them up.
It has worked well from the beginning, it is not a mistake.
Honest question: as a GC’d language, D seems to occupy the same niches as Go, JVM-based, and CLR-based languages rather than that of C++. Wouldn’t it be more accurate to compare to them than C/C++? Am I misunderstanding something?
Ah! Okay, that’s what I was missing. I found the blog posts on using malloc and free from D. I knew the GC could be disabled, but I wasn’t aware of how practical it was to manually manage memory. Thanks!
I'd put C++ as being between C and D, as D leaves a lot of things behind like the preprocessor.