Hacker News new | past | comments | ask | show | jobs | submit login

I used to write a lot of C++ (like 14 years ago at this point). I haven't really paid any attention to it in that time. I am looking at the code examples and what I see is a language trying to adopt features from Java, Rust and others - but where in those other respective languages there's like just 1 thing going on in a single line of code. In these C++ examples you have the namespacing stuff, templates/generics, implicit operators and constructor calls. It just feels like exactly what you would expect of a language like C++ to try to adopt the native features of these other languages. Which isn't a bad thing, but it just screams to me like wouldn't it just be easier to switch languages?

That all being said, I do get the "rush" C/C++ programmers feel when they write multi-threaded socket servers. You step back and go whoa - that worked?




It is, in fact, never a surprise when a modern C++ program runs the first time without faults. That is an important difference from C, and a quality it shares with Rust.

What is missed by the authors of all articles of this kind is that, while all of the errors cited are possible, none are tempting.

For example, while it is easy enough to overindex an std::vector<T>, the language provides a "for" statement that exactly walks the vector with no possibility of overrun.

Using an empty std::optional<T> may seem like a danger, but nobody uses one unaware that it might be empty; it needs different syntax to look into than a regular value.

std::string_view and span, similarly, may seem foolishly risky, but they are always safe when passed down a call chain. One does not find them returned from functions in a responsibly designed codebase.

C++ is a box of sharp tools that a responsible engineer can use to make fine, reliable software. We have, today, many, many times more responsible engineers writing good C++ code than we have Rust coders in total.

Work making C++ code safe and reliable thus has a much bigger impact on the world than anything ever done with Rust. That will be true for a long time to come. That is not a reason to avoid Rust, but it is a reason to remain respectful in interaction with those engineers.


Modern C++ is extremely powerful, more so than any other systems language, but not simple. I’m not even a fan of the language per se, but there aren’t any alternatives currently that are as powerful or expressive and I actually use that power pretty regularly. You can’t express modern C++ in other languages with similar code gen in remotely similar lines of code, which is its unique strength.

In my experience, if you use the full idiomatic toolbox of modern C++, code mostly works the first time. That was never the case when I was writing C, or even legacy C++ (which was terrible).


> wouldn't it just be easier to switch languages

Unfortunately in many cases no, which is the problem


> 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."




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: