I haven't managed to read through these last few pages but I just wanted to chime with my noob opinion re: D slices, templates, GC and manual allocation, for whatever its worth:

Although I tend to just let the GC do its thing most of the time, I've found spots where I needed manual allocation while retaining all of the nice features like appending, but at high speed (because yes, the speed on GC-supported append is painful). Between template mixins and operator overloading and the ability to drop down to the C level, D absolutely provides you with everything you need do handle all of this yourself while retaining as many advanced features as you care to implement in your specialized memory-management system. With alias this and opDispatch, its not even that much work, and with contracts and template constraints, can be made quite safe as well.

What I want to emphasize is that you would be doing all of this in C++ anyway, but with a much more difficult template system, nastier syntax and lots of gotchas and corner-cases. The only thing that I miss from C++ is move semantics, but the few times I've felt like I needed them (like a struct relying on internal references, say, to a containing struct) I was better served by mixin template (which take on the local scope, obviating the need for internal refs in my use case... YMMV of course).

But what you wouldn't get with C++ is GC by default, which is nice when prototyping, need some advanced data structures and don't want to waste time worrying about memory layouts and move semantics for something that, in all likelihood, will be a throwaway (or at least subject to extreme modification).

With D you get flexibility by default, and speed when you need it. Even without the support of all the GC'd features, you're still left with a wealth of (generally zero runtime overhead) metaprogramming options to help safety and readability. You've got to know what you're doing, of course, but if you are coming from C++ you are already used to being surgical.

tl;dr: If you want to append (to pick out one sugary GC-reliant feature) and you find the builtin too slow, define opOpAssign (string op: `~`)(ref T that) on a custom slice-like struct that forwards ops to a manually allocated backing container. It can't imagine it'd be much slower than a push_back on pre-reserved std::vector.

Reply via email to