Ask HN: Are there any good reasons to use C++ over Rust for new projects today?

61 points by therepl ↗ HN
Hello! My go-to language to develop something that needs high performance has been C++. I do a lot of high frequency transactions, systems programming (implement tiny compilers/interpreters for domain specific problems and such), personal projects, etc. and I usually start my projects in C++. But it is increasingly looking like Rust can solve all the problems that C++ can without losing performance and while gaining better memory safety guarantees and better type invariance guarantees. The packaging story, Cargo, etc. of Rust are definitely very attractive!

So that brings me to the question. Is there any point in starting new projects in C++ anymore?

I don’t want this to turn into a language flame-war. My question is in good faith and I do want to learn from the wisdom of the folks who comment here. People who have been using Rust for much longer than I have can offer valuable insights that I might not know. So to avoid flame-wars, let me make this question as specific as possible:

1. Is there any context in which it makes more sense to start a new project in C++ instead of Rust?

2. For someone like me who is not too experienced in Rust, what are the things I should watch out for or be careful about when starting a new project in Rust?

3. Any other free-form advice you have for someone like me who is considering making Rust my go-to language for doing new projects?

91 comments

[ 3.0 ms ] story [ 187 ms ] thread
Familiarity and library support would be the two obvious reasons.
If you need to interact with existing C++ code or libraries obviously C++ is going to be a much easier path than using Rust. If you don't have such a requirement, or you think that the available Rust libraries are good enough for what you're doing, then use whatever you want.
This is it. C++ has the huge advantage of being able to use the entire ecosystem of existing C++ and C libraries without any kind of bindings.

When you'd need to make your own Rust bindings or rely on some third-party project which may or may not be actively maintained, then C++ is more attractive.

I just started a new project in C++ for two reasons:

1. I already know (some) C++

2. more mature GPU ecosystem, particularly CUDA support

I don't mind learning new languages, so CUDA was the deciding factor for me. Maybe someday as Rust's GPU support improves I'll consider a rewrite.

Direct integration of C source code. Other than that, I can’t think of anything else.
In embedded development, sometimes gcc has been ported to many more architectures than rust(llvm) so unsafe either c or c++ (or fortran).
Consider cross-platform -ness. For example, if you make a new app with domain logic in C++, you can build it on iOS through Swift/Objective-C++ >> C++, or on Android through Java JNI >> C++, or on React Native through JavaScript Interface (JSI) >> C++, or on Linux through wxWidgets >> C++, or... etc.

Other than that, Rust is a great language with a great compiler eliminating whole categories of bugs possible with C++.

I don't disagree that broader platform support is a reason to choose C++, but Rust is just as capable at integrating with the specific platforms you're talking about.
> Rust is just as capable at integrating with the specific platforms you're talking about.

Maybe it’s possible but definitely not as straightforward to use rust on iOS. Compared to C++.

I have not personally used C++ or Rust in this context, so I can’t speak to the ease of either, so could you say more?

The use-cases I know of basically build a library exposing the C ABI, which is slightly annoying but effective. I'm guessing you're referring to Swift <-> C++ interop?

What I mean is that adding C++ files to your iOS project and having them compile and work together without any new compilation steps or settings, and to have Swift code call a C api on your C++ implementation -- all of this is straightforward to do for iOS, and Xcode even creates the "bridging" headers for you and has built-in support for C++. Now, adding Rust into the mix? That will be much more involved and certainly not as simple; nor is it natively supported by the iOS toolset in Xcode. That's what I meant when pushing back on your notion that "Rust is just as capable at integrating with the specific platforms you're talking about."
Thanks!

I wasn't trying to claim that they're equivalently easy: just that they both have the same capabilities, there's nothing special that one can do that the other cannot.

C++ seems easier to work with, tools for C++ are plenty and more mature, so if productivity and speed of development matters, those are good reasons to use C++.
While I can imagine that familiarity with tooling can be a massive boon, I have to say I tend to pick Rust over C++ for the exact opposite reason. I find Rusts tooling a lot easier to use than the C++ tooling. Clear compiler messages showing what's wrong, far easier error handling and logging, and far easier dependency handling through cargo.

On the other hand there's of course the borrow checker which means you need to think a bit more about how you do your lifetimes, which can slow you down a bit, but I find that that prevents me from writing bugs more often than not.

Plenty & mature != Easy to work with. Ever had to run make from within CMake? (so that's a build system generator running a build system while generating a build system...)
I like C++ so that's reason enough for me.
I used to have parallel feelings about Scala as a newer better alternative to Java. Then I ran into some issues with it in the real world. See if there are any parallel, I will copy-paste the issues I reported before:

"There were some problems with Scala in the real world. Compared to Java it had a big learning curve, what with all the features it took from Haskell and functional programming while also keeping all the old features of Java. Some of the libraries weren't as mature as their Java equivalents or there were two equal competing libraries whereas with Java there was just one popular library for a given thing. Hiring Scala developers was an issue. Compile times were bad. Every major version of Scala (ex. 2.10, 2.11, 2.12, etc.) broke backwards compatibility so if you had something with say Scala macros that compiled in Scala 2.10 it wouldn't necessarily compile in Scala 2.11 without code changes. We had a library where the maintainer abandoned it at Scala 2.10 and we couldn't upgrade to Scala 2.11 without either taking the library out and using something else in its place or taking over the library, which just wasn't feasible. There was an issue with Scala that I've seen with C++ as well where the language is so big that different teams and different people program in different "dialects" of the language, using different subsets of language features (ex. some people used OOP class inheritance and some did not). Lots of people didn't get Monads or functional programming. But yeah, lots of places ended up going back to Java or using Node.js if they wanted to be async/reactive. "

This is spot on. Scala is a powerful language and we get a lot of milage out of it, but it's despite the Scala ecosystem, not because of it.
1. Better integration with existing libraries, there is a lot of software the exist in C/C++, and a lot of it is weird and opinionated, and having to write bindings for that isn't great.

2. Continuing on that, QT is still good for large desktop GUI projects. It doesn't seem it's well bound to Rust, and Rust is still trying to figure out their comparable UI story.

3. Ironically, in some certain circumstances, with good discipline, (And mostly interfaces that looks like C) C/C++ can compile faster then Rust.

There's basically no reason to use C++ over Rust in 2024. Other than personal preference, I guess (I grew up with C++ and so it's nostalgic, but it's no Rust).
The benefit of using Rust is that management of 3d party libraries compared to C++ is a lot easier with cargo, so you can do things quicker.

The downside to using Rust is that its still an evolving language so you may have to refactor your code down the line. Generally Rust use case is targeted towards enterprise software, where you have lots of people working on it, and it needs to be fast, and you want to minimize chances of introducing memory bugs. For personal use, I don't think its honestly worth it tbh, it just slows you down.

Personally, I use Python and C exclusively. Its pretty easy to write C extensions to Python to handle the things you need to go fast, and then let Python handle the launching of the code. For example, I was playing around with MCTS, and I would have the tree set up in Python, and then use multiprocessing to split the tree into x processes, and each process would launch C code that did the search a lot faster. Overall the implementation was super easy since I didn't have to write the low level C code for the initial setup, with memory management and so on.

There was a recent video about using torch to compile custom CUDA kernels (https://www.youtube.com/watch?v=nOxKexn3iBo). I have implemented this for some custom data processing that I do that I previously had C code to do on the CPU, and its WAY faster using CUDA.

I've had to refactor a heck of a lot more C++ than Rust. C++11, std::optional, concepts and ranges, std::format, etc. It's not even that I dislike these changes necessarily, but you're always rewriting C++ to keep up with the language.

In rust it's mainly been nightly stuff getting merged to stable, pre-1.0, and async. Much more stable overall.

> you're always rewriting C++ to keep up with the language

If that's what you want to do, which is a big if. I guess strictly speaking the same is true for Rust but in Rust, with it being new, it "feels" more like I should keep up (at least for me). In c++, I would mostly just not mess with old code that works...

I'm approaching this from an enterprise perspective of "how confident am I that this code is safe and correct?"

If you hand me a pile of c++03 code that happens to compile, my confidence in it meeting both of those criteria is fairly low. If you ask the standards committee or bjarnes, what they're going to tell you is to rewrite it in modern C++, which constantly evolves.

Contrast that with rust where it's probably fine if it compiles.

> standards committee or bjarnes, what they're going to tell you is to rewrite it

The same will be true for Rust in 50 years (assuming Rust doesn't die any time soon). If they didn't think it was worth modernizing, they'd just leave C++ alone (which I think they should, but that's another matter).

For old C++, you run valgrind and a linter on it and if nothing comes up it's also "probably fine". At least it's hard for me to think of a situation where the most productive/profitable-for-buisness thing a developer can be doing is modernizing their old C++.

Would you bet your life/money/application security on valgrind and a linter being sufficient to catch all of those issues, knowing that a single mistake invalidates every guarantee the standard gives you? That's the situation we're in with C++.

When you're building old code, the compiler can't check that it upholds the standard to the degree that it can for modern C++. That's why the advice is to update the code, because the tooling can't save you otherwise.

Rust by contrast guarantees that you either have a compiler/runtime bug or the issue is more narrowly localized than "potentially every single line of code". Sure, I'd like better, but it's an improvement.

> Would you bet your life

Definitely not. But it's rare that so much is at stake. I would not bet my life on the borrow checker either, there's a lot of things that can go wrong in a program.

Money is of course a question of how much. Application security is just "the above". The "undefined behavior can explode your PC, travel back in time and become your father" problem is not to be underestimated. However, in cases where old code works well for years but really has some lurking bad UB, one can disable some optimizations and be conservative with compiler choice. A lot of people dislike the trend towards compilers being ever more punishing of UB and I can see their point, while it's of course hard to argue for (let alone find) a balance between performance and some robustness to ubiquitous and almost inevitable code issues.

Rust's giarantees are nice and I sure would prefer working on a modern Rust project than any C++ project, as well as a modern C++ project compared to C99-with-classes. Modernizing existing code is a different matter. I've seen very few attempts at modernizing a big and old C++ codebase, no attempts where it clearly paid off and one attempt where it went wrong...

> If they didn't think it was worth modernizing, they'd just leave C++ alone (which I think they should, but that's another matter).

What about C? That's being modernized too, sometimes with novelties from C++ modernization, like `nullptr`! :p

https://www.open-std.org/JTC1/SC22/WG14/www/docs/n3042.htm

The amount of new syntax and programming concepts being constantly crammed into C is much smaller. If I had to quantity it, I'd estimate that C++ is by now roughly 3.5 programming languages in one while C is maybe 1.5...

The more stuff you have the more problematic (adding foot guns and making it hard to learn a language) it is to add more stuff because it all interacts. And a lot of C++ features interact in bad ways...

I think the biggest reasons to go with c++ over rust would be mature compilers and the relative abundance of mature libraries, and possibly your existing knowledge of the language.

It seems like the bigger question is what are the goals of your project(s)? Like if gaining more experience with rust is a primary goal, then the aforementioned advantages are pretty much moot. OTOH if a project could benefit a lot from leveraging mature compilers and libraries, or if you can't afford the additional time investment associated with becoming proficient with a new language, then c++ may well make more sense.

I think the question could be answered with... why do we use JavaScript at our company? Because there are a lot of libraries that are available and maintained there. Many times the existing libraries are more important than the programming language itself.
Firstly, my background is in Haskell and Rust. I generally defer to safety-conscious languages. So please no responses extolling the virtues of type safety, type systems, etc. I know, I agree, but that doesn't change what I'm going to say.

Rust is awesome, but honestly modern c++ is quickly catching up. Rust has safety going for it, but one of the issues is that sometimes you have to be more inefficient for it (reference counting), and pay the price of code litter (Boxes everywhere). Also, realistically type safety takes time to think about (although not much). Either way, you will spend time playing type golf before your code even runs and compiles.

C++ is strictly more powerful, even ignoring the memory safety. Modern c++ with its smart pointers basically has rust ownership semantics builtin, with the option to fall back to manual memory management, which is sometimes necessary. Modern c++ has concepts, template metaprogramming (MUCH more powerful than rust), constexprs, etc. This alone, for me, has made developing interpreters and compilers much easier in C++ than Rust.

Finally, after almost a decade being a professional Haskell developer I have come to appreciate the benefit of being able to prototype fast. The truth is, type-safe languages are great for final work, but having the option to throw it all out the window to just get something done, is also really nice. In my ideal world, we would have a language with well-defined semantics for ill-typed programs (even with undefined behavior) and then an option to strict-ify the type-checking when releasing. Yes, I know rust has unsafe, and this is good, but maybe I just don't know enough unsafe rust to be efficient. I find it not obvious to use. Haskell of course has a REPL which (in my opinion) makes it easier to prototype in than both Rust and C++, so while it has type safety, the REPL makes prototyping easy. Without either a REPL or an untyped fallback, I think Rust takes more time.

One more thing... Rust has great abstractions, but unlike the Haskell world where abstractions are taken to their logical conclusions fast, it seems to me rust is more conservative in its approach (multi-param traits, for example). This seems to have worked out in terms of popularity. But for me at least, when working with Haskell, I often start to reach for yet more advanced features that really ought to work. Usually, when that feature is not implemented yet, I will find an approved GHC RFC for it, and just wait for the next version of the compiler. In Rust, it seems things move much more slowly. I have found myself endlessly frustrated with what I perceive to be weaknesses in its trait system (no existentials... :( ).

At the end of the day, both are solid programming languages, with Rust being much better for anything dealing with business logic, while C++ is better for projects involving heavy meta-programming. I have personally myself done a lot of prototyping in Haskell (due to the REPL) and then implementing the runtimes in C++. Rust I've used for one-off tools, utilities, and anything to do with high-perf async IO.

Agree with your assessment of C++. A lot of things have improved in modern C++ over the last 10 years, but C++ has a serious PR problem. Part of this is that it's been changing pretty quickly and people wonder if they should come up to speed on modern C++ or just learn something new (like Rust or Carbon) and in many cases people just decided to do the latter because coming up to speed on C++20 is basically like learning a new language anyway.

Still, the remaining big deficiency that C++ has now over more modern languages like Rust is library management. The C++ standards folks seem to say every couple of years that library management is the next big thing on their schedule for the next C++ release, but it gets delayed until later.

Is there a reliable way to enforce some subset of C++? I feel like the biggest disadvantage of C++ is too many features and their unpredictable interaction.
I'm "Rust curious", but I'm coming from a web/app background (Dart, JS, TS, Java, Python), so take my ideas with a grain of salt.

1. One context, which appears to be yours, is when a team or individual has extensive C++ experience.

You see, for me, learning C++ with all its decades of good/bad parts feels overwhelming, so Rust makes sense for me even if it's still the hardest language I've ever learned, but as you are already an experienced C++ dev, it might make sense to continue cpping.

I'm used to simple, standard formatting tools, packaging, dependency management (Rust is great in that sense even for beginners), so to figure out how that's correctly done in cpp in 2023 would be hard. But again, for you, it's easy, you already know all that!

Apart from that, I guess there can be libs that are great in C++ and still lacking in Rust.

Also, need to consider if memory safety is really such a big issue for you and your future project.

Here is my advice on learning C++. Don't learn it first. Learn C first, become good at it. Then ease your way into using certain functionality of C++ in your code, and so on. Don't try to bite it all off at once. I've been developing in C++ for over 30 years now, and I'm still learning something new about it.

Look at it like Mathematics. You learn Algebra, and Trig, but Calculus is a something different. If you don't have a solid understanding of the previous, you're not going to understand the symbolic manipulation of Calculus. It then gets worse from there as you go into Differential Equations.

IMO procedural and imperative programming should be understood before trying to grasp polymorphic, object-oriented and functional programming. There is a lot of abstraction, and training of your mind to abstract is a process.

Be careful, there are purists that exist out there, and they will scream and complain, but ignore them. Don't let others control how you think. A late professor of mine once told me something I thought I understood, but it didn't hit me until years later.

"Any program written in any language that produces the correct results is a correct program."

As long as it does what it is supposed to do, it doesn't matter how you get there.

Also, code purity is myth, and those seeking it are believers in mysticism and false aesthetics. There is good code organization, but when you're up against deadlines, good luck keeping it organized.

This memory safety issue is important, don't get me wrong, but it is completely over blown. SpaceX built incredible rockets and systems in C/C++. We have external tools to check for these issues, and they still need to be used with Rust.

Rust has a method for enforcing better memory safety. That is great for deployed applications, but can be annoying when you’re still exploring / mutating your code to figure out the right shape of things.
I have never had the experience that being precise about what I mean slowed me down, if anything it was the opposite.
because sometimes you don't know precisely what you mean. if you don't already know the shape of your solution the 'safety' features restrain you.
I am a retiring engineer/entrepreneur. I made a lot of money with C++. It is hard for me to tell anyone not to use it.

I recently developed an oil and gas derivative tool in Rust. IMO Rust has a long way to go. It reminds me of OCaml. I spent 2 years developing a Compliance System on DEC/OSF1 in OCaml. We made the mistake of adopting that language too early. Also, the C++ community is a lot more tolerant. A big plus for C++.

In which ways does Rust need to improve, in your opinion?
Here we go. I'm not taking this bait.
(comment deleted)
I’m not trying to bait you, and people who attack you for what you say are morons.

I don’t have much experience in either language, and I don’t have an opinion on which is better. I am just interested in your opinion.

I understand your hesitation, but I’d really appreciate your take, given you seem to know your stuff.

Personally I think the sibling comment is pretty accurate, and rust is held back by:

- slow compiling of larger projects

- async stuff can quickly lead to very complex shenanigans

- embedded still requires you to write HAL stuff for MCUs that is supported out of the box for C

Compile time, async, steep learning curve are things that come to mind
I’ll add, thanks to their age, C and C++ have more compatibility with boards, OS’s, GUI’s, libraries you might need, etc. Especially in embedded, you have way more options if using or hiring for C/C++. There were also more tooling for analyzing the C/C++ software but they often cost $$$.

For common scenarios and platforms, Rust’s library situation did get way better really quickly.

I'm fond of rust, but compared to go, I dislike that you need a different code path to support sync vs async in a module. Or pick a different runtime like Tokio. So you end up with modules that are async only, sync only, or both.

Makes me miss go, which has channels build in, has a runtime built in, and both are generally solid. None of use flavor A for this, use flavor B for that, or write wrappers for the wrong color function.

Rust has channels built in. In fact, the std channels were recently rebuilt on top of the excellent crossbeam crate.

Function colors is kind of a meme but maybe-async functions are coming.

https://lib.rs/tokio is king for std environments, https://lib.rs/embassy for no_std.

Yes, MPSC, single consumer which is limiting.
> Also, the C++ community is a lot more tolerant.

Yeah the biggest turnoff for me with Rust isn't even the language anymore, but the community surrounding it.

I realize it's mostly a vocal minority and the vast majority of Rust people, including the ones I know personally, are very nice. But boy are there some obnoxious Rust evangelists out there.

> Also, the C++ community is a lot more tolerant. A big plus for C++.

Well I completely disagree with this. The C and C++ communities seem to me personally to be a lot more "elitist", engaging in extreme pedantry or dunking on each other over knowing obscure language trivia. Both the language and the community are beginner-hostile in comparison to Rust.

Not that the Rust community is perfect, because it's obviously not - but lack of "tolerance" has never seemed like one of the problems it has.

This echos my personal experience as well.

I would also add that there now seems to be more of an emphasis around being intentional in how languages foster community. The C and C++ communities (in my opinion) became how they are not by design, but mostly by accident or chance.

> I recently developed an oil and gas derivative tool in Rust

Sounds cool! Could you elaborate? Would you have a website somewhere? Do you have any contacts details?

Cheers!

> I made a lot of money with C++.

Please elaborate.

can you share more about how/at what type of jobs you made a lot of money with c++?
One I don't see mentioned here is market. There are far more c++ developers out there. Whether you're writing a library that someone else will be using, or you want to hire people (or have people contribute), c++ is a much larger "market".

This doesn't mean I'm necessarily advocating for c++ or rust, but c++ definitely has advantages over rust, even if they're not just intrinsic.

Rust has good FFI with C++ meaning that you can write Rust libraries that are consumed by C++ programs.

C++ developers understand all of the concepts needed to easily pick up Rust. As long as it's not a quick project that will be immediately thrown away getting C++ to use Rust will be worth it.

Rust has good FFI with C, and do does C++. The Rust <-> C++ FFI experience is still a bit rough.
even C++ <-> C++ is rough as soon as you're dealing with object code...
1. When you need the larger ecosystem of existing/proven software and available developers, then C++ can make more sense. If you are put off by the "NPM-esque" environment (crates.io), that may also be a factor.

2. Can't speak to your situation, and in any case Rust and its "developer experience" are always evolving/improving.

3. If Rust is an option, choose Rust over C++. That's an opinion, but it's quite firmly held.

From my perspective, if you really need the safety guarantees of Rust, use Rust, but if you are more comfortable with C++ and can be more productive with C++, use C++.

Doesn't really make sense to take a productivity hit for small gains in a context where safety isn't a necessity.

Just two cents from a junior person :)

I've heard from some of my colleagues at other companies that Rust has a significant negative impact on developer productivity compared to C++. This makes Rust great for, say, the Linux kernel, where the security and performance features are really needed and the maintainers don't give a rat's ass about how much time and effort it takes for contributors to get their features merged. On the other hand my current company already has significant challenges in the area of developer productivity, and it could very well be that requiring Rust for a new internal project would doom it from the start just for that reason.
My personal experience and that of many people I've spoken or listened to is the opposite. Mozilla and Oxide engineers talk about how much easier refactors are and how much less time is spent mucking around with build systems in Rust.
personal antidote - i've heard this too, but jumping in (after years of python/typescript), i'm blown away by how productive i can be. it's easily my favorite language.

the hiring pool may be smaller, but don't believe the fear.

I can't confirm that. Rust's safety features allow moving fast without fear of subtle bugs.

Developing in Rust can feel like fighting the compiler though when choosing approaches / architecture that aren't a good fit for Rust. This happens a lot when people only have little Rust experience. For example: Writing a linked list can be quite challenging in Rust due to self-referential types. With more experience in Rust, developer learn how to best structure the code so that it doesn't result in this friction.

You really want to be using C++ and Rust as little as possible - ideally only for high-performance code. The rest of your application should be developed using a RAD language like C# or Kotlin. Interoperability between C# and C++ right now is really great with first-party build tooling support from MS. Rust, as far as I know, doesn't have a great interoperability story with any other language except for, ironically, C++ based on this[0].

[0]https://www.hobofan.com/rust-interop/