A lot of the cool stuff being integrated in modern C++ has been present in D for ages ('enum class', 'string_view', 'constexpr', 'auto', ...) ... D has a real module system (=it compiles fast) and an extremely powerfull template system. It's one of the rare languages allowing introspection (e.g you can statically loop over a struct members) without bringing in "dynamic" stuff (e.g add members at runtime, etc.).
For at least some problems people will not want to use a GC, and D's story there isn't as good as Rust's.
However, the garbage collection in D turns out not to be an issue in practice. In D, you do have destructors and deterministic deallocation when you want to (in one word: RAII).
Now you can build systems that detect cycles who lack ownership outside of the cycle and break them. We call those systems garbage collectors.
Eh. Often the whole "ownership" thing is irrelevant. For a lot of high-level programs, trying to express things in a Rust-ish "ownership" style with pointers adds a lot of syntactic and semantic overhead.
I don't see how it can ever be irrelevant, unless you use immutable data structures everywhere. Does your class/struct provide getters? Ownership! You have to think about what you return. When you are not careful, the calling code can break invariants of the data structure. Consider the following Go code:
type Foo struct {
sortedSlice []Bar
// ....
}
func (f *Foo) sorted() []Bar {
return f.sortSlice // Outside world can break invariants.
}
Now the outside world has access to internal state and can break invariants (make sortedSlice unsorted). You have to decide to: make a copy (and waste time) or document this fact (and put the burden on the user of Foo). Suddenly, knowing from the signature what the ownership is and having the compiler fail on violations, looks pretty useful!Tony Hoare once called the null pointer his one billion dollar mistake. I think the lack of ownership semantics (or immutability) is an even bigger mistake. Some of the most difficult and aggravating bugs that I encountered (even in relatively simple web services) were caused by (a lack of understanding of) ownership. Throw in some concurrency and you have bugs that occur frequently, but are terribly hard to reproduce consistently.
Garbage collection trades the problems gc brings with less program complexity and programmer time. It's a degree of freedom that one can choose (if one can choose the language one uses).
"Reserve memory for this entity when I declare it and release it when I don't seem to be using anymore" is huge leap in getting computers to assist us in our tasks. But sure, there are lot of problems domains where this is not a good thing.
GC is indeed a hack: it approximates an infinite memory system on systems that have finite memory. Reference counting is a worse hack: it approximates a GC on languages/systems that can't afford a real GC.
And I say this as a C++ programmer that has written very little code on GC'd languages.
How does that avoid race conditions? What happens if I quickly move my pointer around? i.e. b=a;a=null;c=b;b=null;d=c... etc
We're working at making it much better. Recently added, for example, is the ability to catch exceptions thrown by C++ code.
I'm not sure why this is, as D would seem a perfect fit for writing stuff for the Raspberry Pi and similar; the other usual suspects have focused on ARM support almost from day 1.
Lending a hand there it's been near the top of the list of "things I'd like to do if I had some spare time" for a long time, but I haven't come around that yet. It looks like a fun project, and not one you come across often. Want to write "Helped port a major programming language to ARM" on your resumé? Hurry up!