The C++ code I write these days is actually pretty similar to Rust: everything is explicit, lots of strong types, very simple and clear lifetimes (arenas, pools), non-owning handles instead of pointers. The only difference in practice is that the build systems are different and that the Rust compiler is more helpful (both in catching bugs and reporting errors). Neither a huge deal if you have a proper build and testing setup and when everybody on your team is pretty experienced.
By the way, using "atoi" in a code snippet in 2025 and complaining that it is "not ideal" is, well, not ideal.
I still find it basically impossible to get started with a C++ project.
I tried again recently for a proxy I was writing thinking surely things have evolved at this point. Every single package manager couldn’t handle my very basic and very popular dependencies. I mean I tried every single one. This is completely insane to me.
Not to mention just figuring out how to build it after that which was a massive headache and an ongoing one.
Compared to Rust it’s just night and day.
Outside of embedded programming or some special use cases I have literally no idea why anyone would ever write C++. I’m convinced it’s a bunch of masochists
When I've dabbled in C++ recently it has felt like using CMake fetching github repos has been the least painful thing I've tried (dabbled in vcpkg and conan a bit), since most libraries are cmake projects.
I am no expert so take it with a grain of salt, but that was how it felt for me.
I was using fetch content or the like, there is a package that comes after a certain version of cmake where you can tell it this is a git repo and it handles all that for you. It has been a few months since I did this so I don't remember the details fully
> Every single package manager couldn’t handle my very basic and very popular dependencies
Well there's your problem - no serious project uses one.
> I’m convinced it’s a bunch of masochists
People use cpp because it's a mature language with mature tooling and an enormous number of mature libraries. Same exact reason anyone uses any language for serious work.
How can you simultaneously call cpp a mature language with mature tooling and acknowledge that there's no working package manager used by any "serious" project?
Package managers per language are a (relatively) new endeavor. The oldest language I can think of that widely adopted it was Perl. Although, perl was quite ahead of it's time in a lot of ways, and php undid some the work of perl and went back to popularizing include type dependencies instead of formal modules with a package manager.
C++ "gets away" with it because of templates. Many (most?) libraries are mostly templates, or at the very least contain templates. So you're forced into include-style dependencies and it's pretty painless. For a good library, it's often downloading a single file and just #include-ing it.
C++ is getting modules now, and maybe that will spur a new interest in package managers. Or maybe not, it might be too late.
It's a relatively new endeavor, but it's also a requirement in 2025 if you want to be portable. The Linux ecosystem was focusing on installing dependencies system-wide for decades (that's how traditional `./configure.sh` expects things to work), and this approach is just inferior in so many ways.
The shenanigans people get into with CMake, Conan, vcpkg, and so on is a patchwork of nightmares and a huge time sink compared to superior solutions that people have gotten used to in other languages, including Rust.
I don't think it's a requirement and it does actually come with it's own set of foot guns. The problem is that these design decisions impact culture, which is why JS has a culture of importing far too many third-party packages. Which comes with it's own set of risks.
I agree overall that the C or C++ way of doing things is more cumbersome, but I don't think that's enough to write off those languages as a whole.
C++ is _getting_ modules now? You must be kidding. How can this language, that adds more and more and more features every couple of years _still_ not have one of the most fundamental way to modularize code, splitting it into semantic units? Like ... what?! I did not think C++ would be that bad when it comes to foundational aspects of a programming language. This must be the result of silly obsession with OOP. The typical misuse of "we have classes, we don't need modules!". What other explanation could there possibly be for lacking such basic means of code organization.
Modules were added in C++20, but it's taken them this long to be implemented. Right now, only MSVC has full support according to https://en.cppreference.com/w/cpp/20
C++ build systems are notoriously brittle. When porting a project to a new platform, you're never just porting the code, you are also porting your build system. Every single project is bespoke in some way, sometimes because of taste, but most of the time because of necessity.
It works because people spend a huge amount of time to make it work.
This seems hyperbolic. At work we cross compile the same code for a decent number of different platform - six different OS (Linux Mac windows and some embedded ones) over 20odd cpu architectures.
Do you people really not realize how completely asinine you sound with these lowbrow comments? I'll give you a hint: did you know that C also has no package manager?
Yeah, and it's also much worse for it. There's a reason everyone in C uses their own linked list implementation and it's not because it's a platonic ideal of perfect software.
Agreed. Getting started with a C or C++ project is such a pain in the ass that I won't even bother. Then there is the fact that unless you have special requirements that necessitate C/C++, those languages have nothing going for them.
"Mature" means that it has mostly developed to its logical conclusion, and its warts are well-documented and understood, as are workarounds for them. It doesn't say anything about "good", although using mature tooling can be good because (for all the warts) you don't have the rug pulled from underneath you every couple of years, as seen in e.g. JS land.
I think C/C++ are mature in the sense that everyone has gotten tired of trying to fix these issues. But I think we're getting further and further from "well understood" as time goes on. Very few practicing software engineers understand all the nuances of header files, C files, object files, static and dynamic linking, and how different compilers & ABI targets interact with all of that stuff. To say nothing of configure scripts, makefiles, automake & autoconf, pkgconfig, cmake and ninja and all the rest.
Just today, I spent 2 hours trying to get an OS kernel (SeL4) to compile for ARM64. This is an officially supported platform. I ran into a series of problems:
- A recent update to sel4 meant I need to set -DCONFIG_ARM_TLS_REG_TPIDRU for thread-local storage. (Leaving it out is a compiler error). This flag isn't in the configuration script - and it took me awhile to figure out how to set it through cmake + ninja.
- The gcc-aarch64-linux-gnu toolchain was recommended somewhere in the docs. On newer versions of gcc, that pulls in libgcc_eh.a, which tries to use _dl_find_object - which is of course linux only. So the build fails.
- So I swapped to gcc14's aarch64-none-elf cross compiler toolchain, which doesn't assume a dynamic linker is available. gcc-aarch64-none-elf isn't available in apt for some reason, even though the 32 bit counterpart is. From there, I ran into a new compiler error. Turns out the arm gcc toolchains are built against an old version of binutils that didn't have support for SHF_GNU_RETAIN. That is needed for the retain macro to work in C. And retain is used by sel4. This is just a compiler warning, but because sel4 promotes all warnings to errors, the build fails. I could have built my own compiler with a newer binutils. But I ended up just disabling the warning, because you only live once. I briefly tried gcc11 because that's recommended elsewhere in the docs, but gcc11 has the same problem.
All of this headache was from trying to build sel4 - which is all straight C, and one of the highest quality C projects I've ever seen. The codebase is mathematically proven to be correct. But oh my goodness, what a horrendous mess it is trying to work with it. And of course, just to try and get the build process going, I needed to install multiple compilers, ninja, cmake, python and a bunch of random python packages, and google's 'repo' tool to manage dependencies. What is this junk.
Personally I'd prefer to work with clang, but I've had enough pain for one day. And I know swapping compilers will for sure break something else.
If sel4 was written in zig or rust, it would be 10x easier to build and work with. Zig handles cross compilation to any supported platform out of the box. Rust can install toolchains trivially with rustup. Rust also has consistent stability guarantees, ensuring code doesn't "rot" with new compiler versions. And of course, both handle dependencies much, much better. And no need for cmake / ninja / random python scripts to compile. Zig and rust also don't behave differently based on someone else's binutils version. Wtf.
If C is too "mature" to fix these problems, I'm going to switch languages. Sel4 is only 20k lines of code. I wonder if it'd be less work to port it to zig than work with it in C. (I'd consider rust, but rust code can't prevent panics.)
Unfortunely thanks to the "code C in C++ crowd", there is this urban myth that goodies like proper encapsulation, stronger types, RAII, were not even available in pre-C++98, aka C++ARM.
Meanwhile it was one of the reasons after Turbo Pascal, my next favourite programming language became C++.
For me mastering C, after 1992, only became mattered because as professional, that is something that occasionally I have to delve into so better know your tools even if the grip itself has sharp corners, otherwise everytime the option was constrained to either C or C++, I always pick C++.
The strong/weak distinction is a bit fuzzy, but reasonable people can have the opinion that C++ is, in fact, loosely/weakly typed. There are countless ways to bypass the type system, and there are implicit conversions everywhere.
It _is_ statically typed, though, so it falls in a weird category of loosely _and_ statically typed languages.
I think that explicit casts really ought to be discounted, since if you're writing one, you are simply getting what you have asked for. This would be like saying that e.g. Modula-2 is weakly typed because it has bitcast.
That aside, the only remaining footgun in C++ is the implicit numeric conversions. What else did you have in mind?
I mean, the default behavior of single-argument constructors in C++ is implicit conversion. You have to opt into explicit conversions using the `explicit` keyword on constructors and assignment operators.
Then you have all the shenanigans around placement-new and vtables.
If it isn't downright weak, it's also not particularly strong.
The issue with constructors is a real one, yeah. Although forcing `explicit` on single-argument constructors is a single linter rule (which is a good idea for this exact reason...).
OTOH placement-new is pretty much impossible to use by accident. If used intentionally, I don't see it as being any different from an explicit cast - again, you get what you signed up for.
Interestingly in some ways C++ is arguably more typesafe than languages like Java or C#, given how it handles dynamic type of object during construction & destruction...
Meaning you're in a context where you have control on the C++ code you get to write. In my company, lots of people get to update code without strict guidelines. As a result, the code is going to be complex. I'd rather have a simpler and more restrictive language and I'll always favor Rust projects to C++ ones.
That is easy to say today, but I guarantee in 30 year Rust will have rough edges too. People always want some new feature and eventually one comes in that cannot be accommodated nicely.
Of course it will probably not be as bad as C++, but still it will be complex and people will be looking for a simpler language.
Rust has rough edges today. The field of programming is still only a few decades old, and there's no doubt that something even shinier will come along, we just don't know yet what that looks like.
That's not a good reason to stick with inferior tools now, though.
Rust is inferior to C++ for my needs. This is just a reflection on we started a large project in C++ before rust existed, and now have millions of lines. Getting Rust to work with our existing C++ is hard enough as to not be worth it. Rewriting in Rust would cost 1 billion dollars. Thus despite all the problems we have with C++ that Rust would solve, rust is inferior.
(Rust is working on their C++ interoperability story and we are making changes that will allow using Rust in the future so I reserve the right to change this story in a few years, but only time will tell)
I don't think it's a defect of the language that your particular circumstance makes it infeasible to port your project. Having a great C++ interop story would be amazing, but Rust would be decidedly less awesome if it had made concessions in that direction early on.
There's a lot of warts here, particularly around the fact that all Rust types are "trivially relocatable" in C++ parlance. At the same time, figuring out which C++ types are trivially relocatable is pretty difficult. To give you an idea of the current situation, all or most non-POD C++ types must be "pinned" on the Rust side, forcing you to deal with the rather clunky `Pin<&mut T>` API. Either that or heap-allocating all C++ types owned from Rust code. Not great.
I didn't say it was a defect. I said it made rust inferior for me. Those are different things. I don't disagree with rust reasons for making that tradeoff - but the tradeoff as a result makes rust useless for now, for me. If it works for you great.
I think the term "inferior" isn't really appropriate, then. It typically applies to the quality of the thing on its own, not its applicability outside of its stated scope.
By the way, using "atoi" in a code snippet in 2025 and complaining that it is "not ideal" is, well, not ideal.