>
You step back and go whoa - that worked?I did a lot of C++ pre-C++11, and then jumped back straight into C++17, and I confirm the experience of other commenters - in modern C++, "it works the first time" is normal. It wasn't in the old C++, usually when my code didn't crash after compilation, it was a sign there was a gnarly bug hidden :). But the improvements over the past ~15 years made a huge difference.
That said, even though modern C++ is a safety razor, you're still playing with a sharp object. Most of the footguns of yore are still there. Compilers got better at telling you when you're doing something stupid (I can't imagine writing C++ without turning on almost all available warnings), but if you stray away from (or abuse) the modern components, you'll have a bad day. Usually around unintentional dangling references.
The other day I did a quick refactor and managed to crash the app. Reason? I used a unique_ptr after moving from it. Compilers and liters usually catch such dumb mistakes, except in this one case they didn't (neither MSVC, nor Clang, nor clang-tidy). So you still end up overcompensating with tests, hedging against edge cases of your tooling. But it's much, much better than it was before.
> In these C++ examples you have the namespacing stuff, templates/generics, implicit operators and constructor calls.
Yeah, I have two separate pieces of opinion on it.
One, C++ is a peculiar language in which any new addition involves extreme amount of "language lawyering". I imagine the Committee and authors of high-profile libraries to be like people from Suits (the TV show) - figuring out ways to "thread the needle", navigating around all the accumulated rules to make it possible to implement a new feature, possibly with a new DSL, using only the existing features of the language. That's how you end up with ridiculously crazy mess in the templates[0].
Two, C++ is a poster child of Greenspun's Tenth Rule[3]. Standard library has drawn a lot of inspiration from Lisp over the years, and templates are essentially used as a half-working macro system these days. Some Lisp experience is actually useful here, because it lets you discover things you could do with a programming language that you never imagine you could. Knowing both the end goal and how it could be expressed in a language that was designed for it makes it easier to understand the crazier template constructs in C++.
> it just screams to me like wouldn't it just be easier to switch languages?
Maybe. If I were in charge of version 2.0 of the C++ codebase I'm working on, I'd probably consider Rust or .NET. But modern C++ is good enough, and we have good testing & QA culture, so there's no reason to change it. And for people like me, for whom C++ was their gateway to programming, it's actually somewhat pleasurable to work with.
--
[0] - Template metaprogramming is essentially its own separate language since at least C++11, but the community still isn't keen on treating it as such. I'm actually hoping C++ will adopt metaobject protoco... er[1], I mean metaclasses[2] - together with concepts (already in C++20), it might give a chance to "refactor the rules" as it is. Backwards compatibility is the sword of Damocles here, the promise to make a mess forever hanging above any improvement to the language, but the language lawyers are formidable, so maybe they'll make it work.
[1] - See the second opinion. Also https://mastodon.technology/@temporal/104120750692741713.
[2] - http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p070...
[3] - https://en.wikipedia.org/wiki/Greenspun%27s_tenth_rule - "Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp."