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?
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++.
"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. "
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.
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.
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.
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.
Other than that, Rust is a great language with a great compiler eliminating whole categories of bugs possible with C++.
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.
With that said, C++ and Rust both occupy similar domains (high-performance, low-level, often interacts with OS syscalls or hardware).
Pros of C++:
- More mature, excellent library ecosystem, decades of code to reference from.
- Syntax is arguably easier to read and write
- It's very popular (top 6th language on GitHub), lots of talent to hire from.
Pros of Rust:
- Memory safety, it's much harder to introduce bugs of a certain type.
- The borrow checker makes it easier to reason about lifetimes of objects.
- Cargo is great for pulling in libraries (just needs more of them).
For me personally (graphics / game-dev), cost and speed of development is the deciding factor. I use both: C++ by default, and Rust for low-level, safety-critical code.
1. Much faster compilation speed.
2. Having to syntactically specify ownership is annoying and a waste of time in many cases. Unless you need the hand-holding, but then low-level programming isn't for you. :P
3. Multiple compilers. Ironing out bugs is easier when you have both clang, gcc, and msvc.
4. Valgrind and other tools for debugging, profiling, and analysis.
5. Personally, I find Rust's syntax obnoxious and cluttered. With C++, most of the clutter can be avoided which I like.
The second thing I’d point out is that while Rust’s build tooling is obviously very nice for some cases, it’s not a silver bullet and C++ build _is_ a solved problem. It just can be a bit more of a lift to get rolling and add new dependencies, but these are infrequent costs. Adding a Rust component to a non-Rust build chain can be very painful, however. Cargo really wants everything to live in Cargo.
Last but not least, C++ also has extremely mature and comprehensive static and dynamic analysis tooling. It may be that Rust has begun catching up here, I’m not certain.
The real gain Rust brings is in the social dynamics of programming. Junior coders can be involved with low-level code with much less chances of breaking stuff. Seniors can push the envelope further while keeping the code maintainable by future contributors.
In general, Rust sets a much more level playing field. This is a major advantage for any long lived project but it can be hard to see it if you're already set in the ways of C and unconcerned about the lifecycle of code outside of your hands.
I’m curious if they’ve thought that through as it introduces an entire class of bugs Rust inherently protected them from previously.
> Firedancer is written in C, in contrast to the Rust codebase of the original Solana validator
https://firedancer-io.github.io/firedancer/guide/firedancer....
So, if you use rust on a given project, you may end up re-inventing things that could be libraries, due to lack of support, or the libraries having missing features or a poor/poorly-documented API. Normally, auto-generated Rust docs are a good way to learn a library, but generics negate it by ending the link trails.
I think you'll find the tooling, and (non-async, non-generic) syntax of Rust are a step up from C++.
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.
Older c++ programs also had the "perk" of compiling and running even when there was some memory leak or other problem and, in production, many times the deadline is so strict that a developer has to ship something bugged and just add a note somewhere saying "if you use function X, it will freeze or crash". the Rust Compiler won't let you ship a program without fixing the problem first
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 :)
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.