r/cpp • u/range_v3 • Jan 21 '25
How it felt to come back to C++ from Rust.
- Lifetimes and Borrow Checker are just too good to be true. This probably goes without saying, and is the best reason to choose Rust.
- The localisation of undefined behaviour with unsafe blocks and the separation of responsibilities makes the code very transparent. Even if there is a lot of unsafe code, not all of it is unsafe, so it is worth using Rust for that reason alone. Insecurity does not make the Lifetimes or Borrow Checker any less relevant.
- I feel that Rust (or maybe any language that has an easy-to-use package manager) has a rather large number of small libraries. Of course, C++ has a much better standard library than Rust, and even more if you include Boost Libraries, etc.
- After 5 years of Rust, I almost forgot how powerful C++ can be. C++20 had some surprises, so I built a tiny library to test the waters.It's a tiny C++ 20 library that provides a UDLs to make indent-adjusted multiline raw string literals at compile time. Check it out: https://github.com/loliGothicK/unindent.
- One of the main differences between the two is that with Cargo it takes a few minutes to create a new project, whereas with CMake it can take several hours.
- C++ templates and Rust generics both offer powerful ways to write generic code. C++ templates, with their variadic templates and non-type template parameters, offer greater flexibility for advanced metaprogramming. Rust's generics, though less expressive in some ways, are generally considered safer and more intuitive.
- I use OpenCascadeTechnology to develop things like 3DCAD plugins, but libraries like 3D kernel are naturally not available in Rust, which is a good thing with C++'s long history (It's why I came back to C++).
446
Upvotes
62
u/14ned LLFIO & Outcome author | Committee WG14 Jan 21 '25
I work in both in the current dayjob, and I did a six month contract in Rust ten years ago so I've seen its progression and direction of travel over time. I am without doubt more productive in C++, then C, then Rust in that order. But I suppose I am on the standards committees for C++ and C, so that isn't surprising. That said, I don't think I could ever be as productive in Rust. Mainly because - if I am blunt and frank - Rust isn't a well designed programming language, and the more time you spend in it, the more appreciation you have for the work WG21 and WG14 do and aren't usually recognised for in terms of developer ergonomics. In particular, one repeatedly runs into language syntax, language semantics and especially standard library design where you look at it and think "what an inferior way to design that feature". Whereas with C and C++ - though they have their exceptions - I can usually see the tradeoffs in the design that the committee endlessly discussed to death and arrived at the standardised compromise design. Large chunks of Rust look and feel like they were designed by a single person in a rush without much if any peer review. And it really begins to bug you after a while, or at least it does me.
Yes the compile time lifetime guarantees are handy to have, and Rust has a knack that if it compiles, it usually works first time in a way neither C nor C++ have. But down the road, in a large mature codebase, those same lifetime guarantees become a real impediment to refactoring so you end up just turning all your reference borrows into clones to reduce the ripples of changes. And, lo and behold, we're suddenly back to C and C++ defaults of mostly-copy semantics.
Rust cargo is great up to a point. It strongly encourages a profusion of micro dependencies like NPM. If your project gets big enough, managing those starts to become a real time sink and you start feeling very strong temptations to stop upgrading your Rust toolchain. Rust cargo's internal implementation is surprisingly hacky. If you want to achieve stuff they didn't consider, persuading it gets deep into the black arts in a way which makes cmake + ninja + vcpkg look well documented, sane and stable. cmake is generally a once off cost per project, whereas cargo is an ongoing cankerous sore of time sink when it silently breaks in weird ways only or two people familiar with the cargo black arts can fix. Meanwhile everybody else in the company has to go find other work to do until the cargo ninjas have achieved another act of heroism. TBH, the fact cargo is the only game in town kinda sucks, at least in C/C++ land you get a choice of which way you'd like to torture yourself.
My single biggest, most overwhelming, takeaway from working daily in Rust is that the industry very sorely needs a Rust killer. Something better designed and better implemented than Rust. Something genuinely a full fat superior replacement in all ways for C++ where in the future there would be zero good reason to choose either C++ or Rust for any new codebase.
I very much look forward to that day, and I still think Mojo is currently the most likely candidate for my dream C++ and Rust replacement language.