Comment by andyjohnson0
15 hours ago
> This code works. It compiles. It runs. But depending on how you’ve implemented your types, it might be performing thousands of expensive copy operations instead of cheap moves without you realizing it.
I've spent the last two decades in the .net platform. But for a decade or so before that I was a C++/Unix dev. I remember old style "C with classes" C++ as being fairly small and elegant, and approximately as easy to reason about as C# - albeit that you had the overhead of tracking object ownership and deallocation.
What the language has become now, boggles my mind. I get hints of elegance/power and innovation when I read about it, but the sheer number of footguns is astonishing. I'm very sure that I'm not clever enough to understand it.
But some very smart people have guided the language's evolution. So, what are the forces that have determined the current state of C++?
> So, what are the forces that have determined the current state of C++?
I'm very confident that the main driving factors are:
1. "performance" (not wanting to do more allocations than necessary)
2. abi compatibility
3. adding features without caring how well they integrate
Example for 1:
"emplace", you normally have "append" but emplace directly constructs the object in the container instead of having to be constructed first and then moved into the container. This nice and all but breaks when using pairs (for reasons you can google but I don't wanna explain here). So now you have these obscure classes like https://en.cppreference.com/w/cpp/utility/piecewise_construc... which solve this.
Example for 2:
Basically they never break the ABI and this leads to tons of old stuff hanging around and never being changed and just more stuff being added on top. std::iostream is famously slow and a big reason is because you can't fix it without breaking the abi which they don't wanna do.
Example for 3:
The whole template thing adds so much complexity it's bonkers, I think c++ without templates would be pretty manageable comparatively. For example because C++ has constructors and they don't quite mix well with templates you suddenly end up in the situation that you have 2 concepts: "normal" template argument deduction and constructor template argument deduction (CTAD). Because of this asymmetry you need a custom language feature called "deduction guides" to maneuver yourself out of the problems that come from this.
Or another short one: std::expected without something like the "!" that rust has. You end up with endless "if(result.has_value()) { return result; }" cascades and it's horribly unergonomic. So now we have a Result class but it's practically unusable that it will only fragment the ecosystem even more.
>Example for 1: ...breaks when using pairs
No, it doesn't. But sometimes you want to construct pair's elements in-place too and that's what piecewise_construct is for.
Note that C# 14 versus C# 1.0 isn't suffering from feature creap as well.
What has guided C++ are the 300+ volunteers that get to submit papers, travel around the world attending the meetings, and win the election rounds of what gets into the standard.
Unfortunately design by committee doesn't lead to a clear product roadmap.
> So, what are the forces that have determined the current state of C++?
A subset of the language aimed at library writers. As a user of those libraries all these weirdo features are likely to be transparent.
TFA explains how std::move is tricky to use and this is not a feature reserved for library writers
Of course it is not reserved for library writers - nothing is. But it is not a feature that application writers should worry about overmuch.
2 replies →
> old style "C with classes" C++ as being fairly small and elegant
it (C++) never really was that
but it was possible to use it "as if it where that" (kinda, e.g. there is code which is valid in C but UB in C++)
I mean there where also times where books which told you that in C everything "is just bits in memory" where popular/believed/beloved, even through that never really was true outside of some very specific cases (all of CPU without caches, only in order execution, single core, a mostly non-optimizing compiler, and other requirements). It was just that the chance to run into issues was much less likely if you go ~20+ years back into the past so you could kinda use it like that (at some risk, especially wrt. forward compatibility).
Today you find ton of material even about obscure features, complications, hidden food guns, etc. so things do look/feel far more overwhelming IMHO.
That modern C++ is a bit like a different language glued on top of old C++ doesn't exactly help either.