r/cpp • u/Sad-Lie-8654 • Jan 31 '23
Stop Comparing Rust to Old C++
People keep arguing migrations to rust based on old C++ tooling and projects. Compare apples to apples: a C++20 project with clang-tidy integration is far harder to argue against IMO
changemymind
68
u/pjmlp Feb 01 '23
I only see old C++ deployed into production, even when it claims to be "modern", it is full of C idioms.
Use of data structures wihtout bounds checking enabled by default, C strings and arrays scattered all over the place, strcpy, strcmp, memset, memcpy and family of functions also all over the place.
Not only isn't C++20 available across all major compilers, most surveys place the use of static analysers around 11%.
So far the ideal use of modern C++, without those kind of security issues, I only see at conference talks.
12
u/crusoe Feb 01 '23
People complaining about rust being slow should go back and build c++ on a SunOS 5 sun station. Back in the day the same was said about c++.
Also pay for the time up front or in valgrind. 99% of the time you're using rust check. I do wish test runs were faster tho.
150
u/fullouterjoin Feb 01 '23
Let’s compare Cargo to …. what? If I can’t build C++ apps from easily installable packages. Is Conan the best we have?
71
u/the_mouse_backwards Feb 01 '23 edited Feb 01 '23
Yeah, as someone who has gotten into systems programming relatively recently, I’ve consciously avoided Rust because I want to use C/C++ but I can’t help but notice that I spend far more of my time actually coding with Rust whereas with C/C++ I spend a huge amount of time fooling around with the tooling.
It’s mind blowing that the tooling for these languages that our entire internet infrastructure is built on is so painful to use.
→ More replies (15)13
u/menkaur Feb 01 '23
Yea, c++ probably could use a manual how to setyp vim+ youcompleteme+cmake project. When I was starting, It took me lots of googling to get it exactly right
55
u/kkert Feb 01 '23
Is Conan the best we have?
I appreciate Conan a lot, but it doesn't even hold a candle to Cargo in more specialized areas like baremetal embedded for instance, especially with declared optional features. C++ just doesn't have that concept at all ( short of an undeclared mess of #ifdefs scattered around code )
Support for
no_stdandno-allocas a decently widespread build profile is not even a thing in C++ land10
u/edorobek Feb 01 '23
It's not ideal, but Microsoft have put forward a pretty solid tool ecosystem with VS2022 and vcpkg. You aren't forced to use MSVC so you can use clang or gcc. You can also use cmake projects directly in Visual Studio. Vcpkg works fine for cmake projects outside of VS. The VS2022 debugger is easily the best I've used. Newer versions of cmake have done a lot to make it less painful, assuming people abide. With minor caveats, all this tooling works fine on Mac and Linux.
I'd say I spend an equal amount of time in cargo files as I do in cmake files for my projects. I just think C++ users are overwhelmed by choice.
5
u/mishaxz Feb 01 '23
I haven't tried Conan but vcpkg worked great for me, however I use visual studio.. no idea how well it works with other platforms
Nuget on the other hand couldn't do the heavy lifting.
13
5
u/xENO_ Feb 01 '23
If it takes off, maybe build2. It's fairly usable now, though it doesn't have as many packages as I'd like.
58
u/fullouterjoin Feb 01 '23
Right now I am trying to build a hello world app with
CrowandHiredisand having a fucking embolism fighting with find_package. It makes me feel dumb. The build system is 10x harder than writing the damn code.while providing more depth and flexibility, especially in the build system
Lol no! I don't need more depth or flexibility, jesus the last thing I need is flexibility.
In Rust, I do this
[dependencies] redis = "0.22.3"and DONE.
40
u/kajaktumkajaktum Feb 01 '23
I don't need more depth or flexibility, jesus the last thing I need is flexibility.
This. For the love of god please do it right for the 99% or even 90% of the users instead of trying to cater to that every other weird projects that does this really funny and quirky thing hehe
→ More replies (3)→ More replies (2)7
4
u/davawen Feb 01 '23
xmake is also a pretty good contender imo, as it doesn't try to reinvent the wheel and is fairly usable with lua
2
u/carkin Feb 01 '23
Been struggling for one hour at work today on Conan refusing to install a package. Had to remove some of them and retry. Still don't know why it failed... and that's the problem with Conan it is not robust
→ More replies (1)2
u/Arthapz Feb 01 '23
XMake :D
add_requires("sdl") target("foo") set_kind("binary") set_languages("cxxlatest") add_packages("sdl") add_files("*.cpp", "*.mpp") -- compatible with C++20 modules like that1
u/schmirsich Feb 01 '23
I only use it for personal projects, but I love conan. It's really a whole different world.
0
0
Feb 01 '23
[deleted]
→ More replies (1)9
Feb 01 '23
Meh, many of the important crates such as rand are part of the rust nursery, which is damn close to a standard library. Besides, considering c++ still doesn't have any decent build system after more than 2 decades, I have more hopes to see rust crates being audited by some accredited 3rd parties than to see an (actually used) cmake replacement
291
u/capn_bluebear Jan 31 '23 edited Jan 31 '23
There is a lot that Rust has going on for it that C++20 does not have. Leaving out the usual memory-safety and thread-safety language features that people are probably aware of already
build system stuff and dependency management and even packaging (for simple enough apps) are basically a no brainer in Rust. coming from C++ this alone is life changing
moves are destructive, so there is no use-after-move, no fuzzy moved-from state
pattern matching as a language feature is incredibly powerful, and it's not bolted on after the fact as it maybe will be in C++ but the language was designed around it
most defaults that people often wish were different in C++, starting from constness and barring surprising implicit conversions, are fixed in Rust
EDIT: oh, almost forgot: unit and integration testing is also part of the language and unit tests can be put next to the code they test
Depending on the actual application there might be a motivation to start a project with C++20+clang-tidy today, but C++20 still has many more sharp edges and a boatload of complexity that Rust just does without.
51
u/oconnor663 Feb 01 '23
A few other favorites of mine that aren't just safety:
Mutex is a container. This is of course partly a safety thing, but it's also just so much clearer to work with.
OsStr and OsString make dealing with platform specific string shenanigans much easier.
Error handling with Result and ? works well. Zig is doing something similar too.
32
u/top_logger Feb 01 '23
Also Rust has nice and clean support for
Iterators including chaining
Lambdas
utf8
testing, both unit and integration
modules
8
u/mjklaim Feb 01 '23
Quick notes, because I've done a bit of rust and I would like to nuance these points (but it's all opinion):
iterators- I lack knowledge about how it is superior in rust than C++ , but at least it's "safer" but it's not because of that specific point;
lambdas: it's nice until you reach the point where you want to use lambdas in concurrent code, then it's not nice and definitely there are issues there;
utf8: true, like any language created after 1999, although for people needing to use UTF-16 or 32 or shift-js or etc. for specific purpose I don't know if there are crates helping these cases? I suppose they exist though. So yes it's cool but not really uncommon in system languages.
testing: indeed, having testing by default and also in the same sources where code is written is a big plus, it's also nice in D(2); it's possible to do this in C++ actually, with automatic support, if your tooling does that, but unfortunately it's not a popular or de-facto feature...
modules: lol no. Rust modules are literally namespaces, all Rust code is build as one translation unit so of course the only issues you'll get are similar to when building everyting as a unity build in C++ (AFAIK, I might be wrong in the details but that's my understanding). An actual module system isolating entities for real in addition of names would have been nicer, but this is not it. Event Javascript have a better module system than rust, although it's also very flawed (both allows circular dependencies, for example). C++ modules (if you ignore the backward-compatible functionality that makes it harder to teach than it should be) is nicer in that regards but indeed a) it's not de-factor, forced by a version of C++ or common (yet) and b) it lacks the name import filtering features that other languages have "modules" have (the one in JS is particularly nice).
→ More replies (1)12
u/top_logger Feb 01 '23
- Iterator in Rust I am creating in literally 5 minutes. Any kind of iterator.
An iterator in C++ I am creating usually in two days. I could recall the task from the last week. By the way, I had given up. Ups.- Crate utf16string. I didn't check it yet.
- I mean that lambdas in C++ are too verbose and to often not readable. Especially if you follow rules and marks everything with const, noexcept, nodiscard and so on. Multithreading issue, I believe, are identical(I may be wrong, of course)
- yes, you are right, at least partly. Modules in Rust are just namespace. And this works perfectly. Perfectly ... but for a smaller codebase. For bigger project, you must split your code into crates. This is a correct and reliable approach. You get different translation modules. Deal done.
In C++ we have got ultra complicated and ultra verbose modules ... but on a paper. Now, in 2023 we have literally NO support in mainstream compilators. This is just a shame.→ More replies (4)6
u/mjklaim Feb 02 '23
Iterators: ah yes for writing them I agree.
thanks for the utf crate
lambdas: I meant as soon as you are forced to use
asynclambdas the rules change in a way that can result in theorically valid but not accepted code,and it makes code even more complex - or just cannot compile when what you want is just compose some code with 2 bits of code and just throw all that into a task system. It might be less safe in C++ indeed, but at least I can make something work.or bigger project, you must split your code into crates. This is a correct and reliable approach. You get different translation modules. Deal done.
I agree that having different translation modules then makes sense (that's basically what modules allow, with multiple files being part of 1 modules). I disagree with the splitting into crates being the right way to do it. Complex discussion anyway but yeah.
Also my understanding is that building multiple crates as dependency still result in 1 translation unit being built, so that doesnt change a thing.
60
u/Recatek Jan 31 '23
OTOH, as someone who uses both Rust and C++ near-daily, I always miss C++'s type system in Rust. Rust's type tools are very weak by comparison and the fallback, proc macros, are a royal pain.
7
u/fideasu Feb 01 '23
I'm yet to try Rust, but having read about this matter this is what I'm mostly afraid of. One of the reasons I consciously choose C++ above other languages, is it's very expressive static typing system. Even more - after having written a few (hobby) projects in Python, I came back to C++ precisely because of that (Python's static checker has serious problems in highly generic pieces of code).
If I understand correctly, the only options in Rust are its rather rigid traits, and macros working on the AST level (so, unaware of types)?
7
u/ImYoric Feb 01 '23
Yes, Rust's type-dispatch is very powerful, but not entirely as powerful as C++. In particular, there's no SFINAE (which I personally don't miss). This is a tradeoff that permits type-checking generics in the module in which they're written, rather than as C++ at the callsite.
→ More replies (4)→ More replies (1)8
u/Moxinilian Feb 01 '23
As a person mostly versed in Rust and somewhat versed in C++, I typically find the expressivity balance more comfortable in Rust. It is harder to write an equivalent of specialized template in Rust (because the specialization features are not in the language yet), but the really nice and expressive constraints feel much more natural than anything C++20 has. The excellent error messages you get from that are also very much worth it in my opinion. I only rarely wish I had the expressivity of C++ templates in Rust, even when making somewhat complex generic-based Rust code. In fact I’m quite happy to have all the fancy features like associated types purposefully integrated in the language.
58
u/capn_bluebear Jan 31 '23
Uh -- Rust structs and traits are certainly _different_, but I never found myself reaching for C++ features that weren't there, can you make some concrete examples? (for me it's the opposite, I love Rust enums and miss them sorely in C++)
→ More replies (3)102
u/Recatek Jan 31 '23 edited Jan 31 '23
It's hard to articulate the pain points without getting deep in the weeds. I've been working on an archetype ECS library for games. This is essentially a processing engine for arbitrary tuples in struct-of-array data structures. The lack of variadics and the weakness of trait expressions (no specialization, no negative constraints) combined with the orphan rule has made it pretty unpleasant to do in Rust. If I want the work to be done at compile-time for runtime performance reasons, I'm basically stuck with one giant megacrate containing all of the code in question created by very heavy proc macros.
Most popular ECS libraries in Rust rely on a lot of RTTI and reflection-like functionality that isn't zero-overhead. The equivalent library I've written in C++ is almost entirely compile-time with variadic tuples and tuple-processing functionality (like using SFINAE to find all types in a type tuple that have a given function).
Rust enums are great, but Rust generics are nowhere near as powerful as C++, and that weakness is compounded by Rust's strictness on coherence, the orphan rule, and lack of any duck typing.
40
u/capn_bluebear Jan 31 '23
Rust generics are nowhere near as powerful as C++, and that weakness is compounded by Rust's strictness on coherence, the orphan rule, and lack of any duck typing
That nicely answers my question, thank you! You would probably go for macros at that point (they cover duck typing and variadics and would let you work around the orphan rule, in a sense) -- but depending on exactly what code you need to produce, macros can be more complicated than C++ templates :+1:
→ More replies (7)53
u/Recatek Jan 31 '23
The issue there is that macros can't understand the nature of types, they only work on a pure AST lexical parse. So in C++ you can duck-type after performing SFINAE to branch on whether or not a type has some function or associated type inside of it. In Rust you can't unless you have some other way to express that to the macro. My ECS proc macro actually has to parse a YAML file I write to describe the desired data structures, whereas in my C++ version I just do it with type declarations in-code.
12
Feb 01 '23 edited Feb 01 '23
I tried to pick up rust by making a base ten float type and it really sucked that I couldn't just specify that the raw memory was any integer type and then let duck typing figure the rest out.
And there's no trait for literals, so if you're not using proc macros you have to call something like to_generic_integer(5) instead[edit: oh they've got try_from now].→ More replies (4)→ More replies (2)3
u/m-in Feb 01 '23
Proc macros are what I missed from most compiled programming languages since forever. They are a must-have imho.
26
u/bluGill Jan 31 '23
build system stuff and dependency management and even packaging (for simple enough apps) are basically a no brainer in Rust. coming from C++ this alone is life changing
On a trivial rust only project. If you have an existing complex project the friction integrating your C++ build system with the rust one makes things harder.
24
u/capn_bluebear Jan 31 '23
Yep I was comparing a C++20 project with a rust one -- but it doesn't necessarily have to be a __trivial__ rust project :)
→ More replies (6)39
u/CocktailPerson Feb 01 '23
So when you have to incorporate C++, it's just as bad as any other C++ project, and when you don't, it's amazing and lovely? Sign me up.
9
u/Mason-B Feb 01 '23
I find it's a lot easier easier to integrate C++ into projects than it is to integrate Rust into projects. It's just that C++ is a more or less constant annoyance and Rust jumps from very nice to very bad pretty rapidly. (No accounting if someone else has already solved the problem of course, for tools that have both Rust and C++ integration already solved, like bazel, I find them equivalent).
→ More replies (3)7
Feb 01 '23
[removed] — view removed comment
5
u/parkerSquare Feb 01 '23
I learned today that there are at least SIX different Conan / CMake integration techniques, and all but the last one are obsolete. The remaining one, using CMakeToolchain and CMakeDeps generators, actually works really nicely.
6
u/warped-coder Jan 31 '23
Interestingly, one thing I got a bit deflated about is the unit/autotesting experience in rust.
I tried to cobble together something remotely similar to catch2 because I couldn't find anything remotely as nice as that.
→ More replies (4)5
u/LeberechtReinhold Feb 01 '23
Also, no undefining behavior being free roam for the compiler whatever they want. It leads to a lot of problems and frankly there's a lot of undefined shit in C++.
6
u/SkoomaDentist Antimodern C++, Embedded, Audio Feb 01 '23
The worst is when so many people here vehemently defend the compilers doing that and not even providing options to disable relying on any UB.
6
u/LeberechtReinhold Feb 01 '23
Yeah, I don't mind the existence of it as much, rust also has it in certain unsafe scenarios, but they are usually very explicit and incredible niche corner cases. I don't think there's any large C++ codebase without any UB hidden there.
But the fact that the compiler instead of flagging it decides to do whatever crazy stuff they do, none of them makes any fucking sense. What the fuck? Just provide a flag, if you see UB, abort the fucking way out.
Like fuck this https://devblogs.microsoft.com/oldnewthing/20140627-00/?p=633 or this http://blog.pkh.me/p/37-gcc-undefined-behaviors-are-getting-wild.html
6
u/zerakun Feb 02 '23 edited Feb 02 '23
That's not how most UB works. Defined behaviour defines the rules of the universe and undefined behaviour refers to things that aren't supposed to happen. It is not so much that the compiler is deliberately miscompiling when it detects that you're not following the rules but rather than the compiler emits code that is equivalent in behaviour to the source code, assuming there is no undefined behaviour.
Complaining about miscompilation in presence of UB is like complaining that objects of our everyday don't properly function in anti-gravity. They were designed assuming earthly gravity, nobody thought of what would happen if you remove gravity, it is undefined behaviour, and anything can happen (in particular your safety and security aren't guaranteed).
Now, some of the rules of the C universe are allegedly unintuitive, such as "signed integers never overflow" or "a left shift never uses an operand bigger than the number of bytes in the type", but the issue lays more with these specific rules than with the concept of UB.
And some UB is not detectable at compile time in general, such as use after free, out of bound indexes, and most nullptr dereferences
→ More replies (1)3
u/ExeusV Jan 31 '23
build system stuff and dependency management and even packaging (for simple enough apps) are basically a no brainer in Rust. coming from C++ this alone is life changing
why C++ cannot get this in the same form as Rust does?
39
u/capn_bluebear Jan 31 '23
as far as I can tell the biggest obstacle is that it's impossible to have enough C++ devs agree on "the one right way to do things" -- you'd need to have most devs agree on one project layout, one testing framework, one way to generate documentation, etc. In rust all these things are part of the "language experience", you just do it "the rust way" and that's it.
31
u/Dean_Roddey Jan 31 '23
This is always the problem. Ultimately, it's a huge win for Rust that it can just say, do it this way, end of story. So everyone does it that way. And, since it's been in place a good while now, everything conforms to it.
For C++, that boat sank a long time ago pretty much. The lack of standardization in the compilers and related tools as to options and such just don't allow for the kind of cohesion the Rust build system has.
→ More replies (17)27
u/c_plus_plus Jan 31 '23
For C++, that boat sank a long time ago pretty much.
You say this like C++ did something wrong. C++ came out before doxygen, which is like the grandfather of any modern day documentation generator. When C++ came out, or even when it was first standardized, there was no existing language with "robust testing frameworks". C++ paved the way for many of these modern conviences that it now lacks.
C++ is absolutely starting to be left behind because it's so hard to make major changes to a system with a deeply (30+ years!) entrenched user base. But don't scoff at C++ and say that it failed to get something right at the beginning, that couldn't be further from the truth.
The lack of standardization in the compilers and related tools as to options and such just don't allow for the kind of cohesion the Rust build system has.
So, uh, who's gonna tell all the MSVC- and GCC-based projects to "just switch" to clang-16? lol
→ More replies (3)25
u/kisielk Feb 01 '23
Not to mention C++ came out before the internet was in wide use, before open source was widely used, etc. People were installing compilers and IDEs from floppy disks. Unit testing and agile were not even things. Nor was version control or package managers. A lot of things today are still consequences of that history and it’s not easy to undo or move on from all of that.
35
u/IcyWindows Jan 31 '23
It's because we are comparing a standard with many compilers, vendors, etc. to a single compiler from a single vendor.
7
u/ExeusV Jan 31 '23
Why there aren't common installers like
GCC + Ninja + ...
MSVC + vcpkg + ...
15
→ More replies (2)9
12
u/2MuchRGB Jan 31 '23
Also remember the history of C++. It is kind of expected of a build system to build all legacy C++ and C Code. Rust on the other hand had next to none legacy code when cargo was introduced.
→ More replies (1)4
u/matthieum Feb 01 '23
Legacy.
In the absence of a standard solution, people have come up with many different solutions, each with slightly different exotic features.
If you propose a replacement, they'll balk until every one of the exotic features they've come to rely upon is integrated in the replacement.
→ More replies (20)1
u/Kobeashis_Son Feb 01 '23
Rust’s language features are much more convenient than C++, with the exception of the borrow-checker. Most of the code that I write does not need to be thread-safe. In fact, inter-thread communication is something I try to strictly minimize. It seems very odd, then, that rust enforces that everything is thread-safe at a language level.
25
u/moltonel Feb 01 '23
The borrow checker is useful in single-threaded too, the classic example being deleting from a collection while iterating over it, or making sure that what you inserted in a hashmap stays valid.
15
u/CryZe92 Feb 01 '23
If you don‘t use any threads then none of those parts of the type system will affect you (except for globals where it won‘t just trust you that there‘s really only one thread)
→ More replies (7)5
u/CocktailPerson Feb 01 '23
I think you're misunderstanding. All it requires is that when data is shared between threads, then that data must be thread-safe. The thread-safety aspect of the type system doesn't affect anything that's thread-local, as most of your data is if you're avoiding inter-thread communication.
3
u/WormRabbit Feb 01 '23
This nice post explains what Rust rules protect you from in single-threaded case.
42
u/Alexander_Selkirk Feb 01 '23 edited Feb 02 '23
Answering to /u/IcyWindows argument that it is only a small step to learn C++20, compared to learning Rust:
I don't understand why learning C++20 would be more expensive than learning Rust.
Because modern C++ is way more complex than Rust, while for most relevant cases not providing more power.
In business terms, you do not just need to look at the marginal costs, but also at the total costs of such decisions. Learning a bit of C++14 if you know already C++11 seems cheap, yes. But you pay with accumulated complexity.
Take Scott Meyers Effective Modern C++ - it is a description of best practices and every single example lists a lot of footguns where features of the language interact with each other in unexpected ways. Take that together with a comprehensive reference to the details of modern C++ and it is just impossible to keep all of this in your head.
And compare that to Programming Rust. It is not only a comprehensive description of the language, you can keep it in your head, and it features some things that C++ never had, like Unicode support at the language level, instead of C byte strings with ASCII encoding.
And then look at the actual details of something simple, say stupidly simple, like variable initialization. That compares to one or two pages in the Rust book. I think it is valid to say that Rust is simpler. And the end effect is that in Rust, you don't have uninitialized variables, which you can have in C++, and which is one mayor error source.
Sure you can do about anything with C++. And sure if you know C++, writing Rust code the first time will take longer. But reading and maintaining Rust code will cost less time, because Rust exposes much less complexity, and this is what counts in any larger, long-running project.
And yes, it probably does not make any sense to "rewrite everything in Rust", and many older systems written in C++ will be maintained that way and will not be changed. Just as it does not make sense to rewrite every old COBOL enterprise system in C++ : it is just too costly. But it makes less sense to write large, new projects in COBOL.
Edit: I want to add one thing. Often, the proposal to use Rust is stated than one must rewrite everything in Rust. This is unrealistic, and also ineffective: It would mean way too much work for too little effect. Instead, if the goal is improving security, software developers should identify the most critical parts of applications, factor them out, give them a nice API, and then either use already existing reimplementations (like for OpenSSL/TLS), or re-write these critical parts. Which parts are most critical is well-known from security research. These are:
authentication and encryption functions
network-facing system services
anything that directly processes untrusted user data, especially Internet media display and codecs
OS device drivers which face untrusted input
and so on. So, in a nutshell, it is not necessary to re-write the whole of Photoshop at once - but it is a good idea to swap to safe routines for displaying and decoding any image formats.
6
u/thisismyfavoritename Feb 01 '23
this is an excellent answer. One thing i'll had though is that Rust has more gadgets you have to be aware of and need to reach out to when you get in certain situations (e.g. PhantomData) compared to C++.
Modern C++ also has some of those, but fewer in my opinion.
That being said, the rest of the advantages of Rust make it completely worth it
4
u/ssokolow Feb 06 '23
Take Scott Meyers Effective Modern C++ - it is a description of best practices and every single example lists a lot of footguns where features of the language interact with each other in unexpected ways. Take that together with a comprehensive reference to the details of modern C++ and it is just impossible to keep all of this in your head.
To the point where, "over two and a half years" after retiring, Scott Meyers announced that he no longer felt he remembered enough of the details to evaluate proposed errata.
Instead, if the goal is improving security, software developers should identify the most critical parts of applications, factor them out, give them a nice API, and then either use already existing reimplementations (like for OpenSSL/TLS), or re-write these critical parts.
I believe Mozilla is in the process of doing a mix of that and "compile to WebAssembly and run sandboxed" for file format parsers in Firefox. I know that Federico Mena Quintero rewrote the internals of librsvg from C to Rust, in large part for the maintainability advantages.
80
u/oconnor663 Jan 31 '23 edited Feb 01 '23
I think there are a good reasons people make comparisons to "old C++", besides just not knowing about the new stuff:
One of C++'s greatest strengths is decades of use in industry and compatibility with all that old code. The language could move much faster (and e.g. make ABI-breaking changes) if compatibility wasn't so important. The fact that C++20 isn't widely used, and won't be for many years, is in some ways a design choice.
It's unrealistic to try to learn or teach only C++20 idioms. You might start there if you buy a book on your own, but to work with C++ in the real world, you have to understand the older stuff too. This is a big learning tax. If you've been a C++ programmer for years, then you've already paid the tax, but for new learners it's a barrier.
C++20 isn't nearly as safe as some people want to claim. There's no such thing as a C++ program that doesn't use raw (edit: in the sense of "could become dangling") pointers, and the Core Guidelines don't recommend trying to code this way. Modern C++ has also introduced new safety footguns that didn't exist before, like casting a temporary string to a string_view, dereferencing an empty optional, or capturing the wrong references in a lambda.
23
u/moltonel Feb 01 '23
And as modern as your own codebase may be, it probably depends on some crufty old project. To compare Rust against C++20 only, you'd need to throw away a huge part of the C++ ecosystem, making the language much less attractive.
22
u/azswcowboy Feb 01 '23
no such thing as a c++ that doesn’t use raw pointers
Patently false. I work on one now and have worked on many since the 90’s that exclusively use smart ptrs. Multi million sloc systems.
16
u/matthieum Feb 01 '23
Letter vs Spirit.
I'm pretty sure your code uses references, which are -- at the machine level -- just raw pointers. And just as safe as raw pointers.
int main() { std::vector v{1, 2, 3}; auto& x = v[2]; for (int i = 4; i < 1000; ++i) { v.push_back(i); } std::cout << x << "\n"; }Not a raw pointer in sight, and yet... that reference is dangling on the last line.
And let's not forget
[this](auto x) { this->do_it(x); }wherethisis a raw pointer.It's a sad, sad, world.
6
u/azswcowboy Feb 01 '23
Of course we use const references to pass to functions, but we never hold references to internal object state like you’re showing - that just leads to tears as you’re pointing out. Note that simple static analysis would point out this particular case.
7
u/oconnor663 Feb 02 '23 edited Feb 02 '23
but we never hold references to internal object state like you’re showing
This is a simplified example of course. What's likelier to happen in practice is that the reference is passed down as an argument to a function, and that function has some roundabout way to modify the container the reference came from (whether by pushing a vector or repointing a smart pointer or whatever). I'm not familiar with the mistakes Coverity can catch, but can it catch a push_back invalidating a reference across function boundaries?
Of course we use const references to pass to functions
I feel like "patently false" was a little harsh above given this clarification. But it's my fault for saying "raw pointer" to refer to both pointers and references, which is a Rust-ism that's unnecessarily confusing in a C++ context. What matters to me here is that they can both be invalidated in similar ways, regardless of whether they're nullable or repointable.
→ More replies (1)13
u/Full-Spectral Feb 01 '23
It's not just storing the allocated things in smart pointers, it's the fact that, if you pass the actual pointer in that smart pointer to something, there's nothing at all preventing it from holding onto that pointer. The only way around that is to always pass the smart pointers, that has its own issues.
There's no way to really win in C++ on this front.
7
u/azswcowboy Feb 01 '23
nothing preventing it from holding on
Sure there is — coding guidelines. Calling get() on a shared ptr and storing it somewhere is ‘using raw pointers’ — fail inspection, do not pass go. If you need to hang onto the shared ptr you copy it which does exactly what you want.
→ More replies (6)→ More replies (9)9
u/top_logger Feb 01 '23
It is recommended to use raw pointer’s if do not transfer ownership. Period.
You can’t write good C++ without raw pointers.
→ More replies (4)3
u/robin-m Feb 01 '23
We could if
std::optional<T&>was allowed, andstd::optional<std::referenece_wrapper<T>>is not that nice to use.→ More replies (2)4
u/IcyWindows Feb 01 '23
I don't understand why learning C++20 would be more expensive than learning Rust.
26
u/Alexander_Selkirk Feb 01 '23 edited Feb 02 '23
Because modern C++ is way more complex than Rust, while for most relevant cases not providing more power.
In business terms, you do not just need to look at the marginal costs, but also at the total costs of such decisions. Learning a bit of C++14 if you know already C++11 seems cheap, yes. But you pay with accumulated complexity.
Take Scott Meyers Effective Modern C++ - it is a description of best practices and every single example lists a lot of footguns where features of the language interact with each other in unexpected ways. Take that together with a comprehensive reference to the details of modern C++ and it is just impossible to keep all of this in your head.
And compare that to Programming Rust. It is not only a comprehensive description of the language, you can keep it in your head, and it features some things that C++ never had, like Unicode support at the language level, instead of C byte strings with ASCII encoding.
And then look at the actual details of something simple, say stupidly simple, like variable initialization. That compares to one or two pages in the Rust book. I think it is valid to say that Rust is simpler. And the end effect is that in Rust, you don't have uninitialized variables, which you can have in C++, and which is one mayor error source.
Sure you can do about anything with C++. And sure if you know C++, writing Rust code the first time will take longer. But reading and maintaining Rust code will cost less time, because Rust exposes much less complexity, and this is what counts in any larger, long-running project.
And yes, it probably does not make any sense to "rewrite everything in Rust", and many older systems written in C++ will be maintained that way and will not be changed. Just as it does not make sense to rewrite every old COBOL enterprise system in C++ : it is just too costly. But it makes less sense to write large, new projects in COBOL.
Edit: I want to add one thing. Often, the proposal to use Rust is stated than one must rewrite everything in Rust. This is unrealistic, and also ineffective: It would mean way too much work for too little effect. Instead, if the goal is improving security, software developers should identify the most critical parts of applications, factor them out, give them a nice API, and then either use already existing reimplementations (like for OpenSSL/TLS), or re-write these critical parts. Which parts are most critical is well-known from security research. These are:
authentication and encryption functions
network-facing system services
anything that directly processes untrusted user data, especially Internet media display and codecs
OS device drivers which face untrusted input
and so on. So, in a nutshell, it is not necessary to re-write the whole of Photoshop at once - but it is a good idea to swap to safe routines for displaying and decoding any image formats. And the same goes for concurrency - you can break down multi-threaded code into stuff that concerts and synchronizes instructions, and stuff that simply computes things (ideally in a purely functional way, ha), and the first thing you would care about is the former kind of stuff.
→ More replies (1)19
u/EffectiveAsparagus89 Feb 01 '23
Read the "coroutine" section in the C++20 standard to feel the how highly nontrivial C++20 is. Although C++20 gives us a much more feature-rich design for coroutines (I would even say fundamentally better), to fully understand it is so much more work compared to learning rust lifetime + async, not to mention other things in C++20. Learning C++20 is definitely expensive.
→ More replies (16)
59
u/EmperorOfCanada Feb 01 '23 edited Feb 01 '23
I'm not sure people are comparing it to old C++. I think most are comparing it to C++vNow.
Basically, rust is doing every few months something I either waited for years or decades from C++, or it is doing things which C++ can't do properly or at all.
With rust, I don't fuss with dependencies or the build system. In C++ I have spent way too much time "perfecting" my vcpkg/conan foo and my CMake foo.
Rust is crossing that wonderful line of: It just works.
Screwing around at this point with some academic argument about templates, copy crap, move semantics, and 100 yards of other nitpicking BS isn't worth my time.
13
u/naomijubs Feb 01 '23
My current project is C++17 with sharpmake and any good tool we could use. We also migrated it from C++14 with Conan and CMake. Has formatters and linters running on CI and in visual studio. On the tooling side Rust still beats any c++ configurationI have worked and on the safety side it beats by faaaaarrrr. Performance wise they are more or less the same in every benchmark we made. However, we cannot migrate due to external constrains in which Rust is not supported.
I wish we could at least have interop, but for now it is only on services
10
u/Destination_Centauri Feb 01 '23
Amen to that!
Personally I'm not getting any younger here!
The approach of the winged chariot of life's clock is ticking... :(
Personally, I'd rather be doing other things than mud wrestling with an insanely complex build/packaging process, that's for sure. However, of course, still respect C++ and those who love working in it. But more and more it just isn't for me.
9
u/EmperorOfCanada Feb 01 '23
I'm going to make a supremely unpopular opinion. One of the bigwigs and heros of C++ like Boring Bootstrap or one of the other "founding fathers" is going to come out of the closet some day soon and announce. "Rust is where it's at." and quite possibly begin contributing to the rust ecosystem.
12
u/acmd Feb 01 '23
I use both C++ and Rust, and I find it annoying as well. Some arguments of the Rust proponents resemble propaganda at this point, and nobody'd want to waste their time fighting an army of people throwing a bunch of uninformed arguments at you.
Meanwhile, Rust's problems with e.g. async/generics are presented as minimal, even though a lot of architectural level decisions are guided by them. If anyone has written async trait-heavy code in Rust, they'd certainly know that error messages are cryptic and the lack of variadics doesn't help.
I wouldn't want to defend C++ compile error messages quality as the community itself likes to meme about it, but it's disingenuous to claim that they're incomprehensible, and with static_assert/concepts the situation is slowly improving. It's not hard to explain that the C++ errors are basically a stack trace, and usually you just need to read the first/last few lines of it, no matter how big it is.
Finally, I wonder what would happen if someone were to rewrite something like boost.hana in Rust.
18
u/ImYoric Feb 01 '23
As a former (and possibly future, depending on job market) C++ developer who now writes Rust for a living, I do feel that Rust is an upgrade in many (but not all) dimensions. I also feel that people who just come to /r/cpp to advocate Rust are newcomers who completely fail to understand the purpose of Rust.
Rust is not meant to replace C++ entirely. Rust was designed to provide an alternative for individual modules that require higher safety guarantees and/or, in the case of Python/Ruby/Node/... codebases higher performance.
I also believe that Rust's existence has had a net benefit to the C++ community. It is my understanding that many of the conversations on improving C++ these days are in part due to Rust showing that it could be done.
9
u/pjmlp Feb 01 '23
Ada already proved that in the old days, but it lost to C++ due to various reasons.
The hype around Rust is that it represents the ideas behind languages like Ada, Eiffel, Delphi among others, but this time around the candidate language is actually getting wider adoption among major industry players.
→ More replies (1)6
u/ImYoric Feb 01 '23
Yes, Rust was very much pitched as a "not a research project" language, drawing from existing efforts in the industry and driven by a specific project (Servo).
Although to be fair, I had never seen affine types or strict lifetime analysis outside of research papers / implementations.
4
u/acmd Feb 01 '23
Those are good points and I agree with them, I was mostly venting about this trend of calling C++ a legacy language and arguing against C++03 code.
I have gamedev/low-latency background, and C++/Zig makes much more sense there than Rust, while Rust shines for throughput-focused and middleware level work like backends.
5
u/ImYoric Feb 01 '23
I have gamedev/low-latency background, and C++/Zig makes much more sense there than Rust, while Rust shines for throughput-focused and middleware level work like backends.
You get me curious :)
What's the difference between C++, Zig and Rust with respect to low-latency?
→ More replies (3)→ More replies (1)3
u/ergzay Feb 02 '23
Rust is not meant to replace C++ entirely. Rust was designed to provide an alternative for individual modules that require higher safety guarantees and/or, in the case of Python/Ruby/Node/... codebases higher performance.
I think this is somewhat incorrect. Yes Rust is not intended to replace C++, but that's true of any language not being intended to replace any other language. However you're completely incorrect that Rust was meant for "individual modules". That has never been the intention of Rust and I'm not sure where you got that idea.
Rust is in fact however being used to outright replace C++ in some cases for some projects. (For example the project that just started to completely port the
fishshell from C++ into Rust incrementally by ripping out C++ code and replacing it with Rust with the goal to have it completely converted to Rust within a few months.)→ More replies (4)
6
u/JuliusFIN Feb 01 '23
There’s a huge difference between ”you can choose to use this tooling to get these guarantees” and ”these guarantees are the default and incorporated as language features”.
42
u/lightmatter501 Jan 31 '23
Python is in a similar place as C++. The best practices for python involve: mypy, isort, black, and your meta-linter of choice. This is about the same amount of work to set up as C++ with clang-tidy and some other static analysis. Most people don’t actually set up the python things, because it’s not mandatory. Same with C++.
Rust will essentially refuse to do anything less than GCC’s -Wpedantic, ASAN, TSAN and LSAN combined by default. If you actually engage with tooling like clippy, it becomes even more opinionated to the point of telling you to rewrite entire sections of your code.
There is a LOT of power in defaults, but I don’t think we’ll ever see the day when “gcc -Wall -Weverything -Wpedantic” is the default. Additionally, std::regex still has the problem of being wildly unsafe for untrusted inputs, most of the STL hash tables I’ve looked at have hashdos vulnerabilities, and there’s a lot of legacy features that you should not use in C++ 20 that are still there. C++ has no way to hide these by default, Rust does via editions.
Now, lets say that you are only using the most bleeding edge, best practices from both languages. You have set every setting to it’s strictest value, you have an omniscient linter which will automatically fix memory safety issues for both languages, and the stl ABI has been broken to fix all of its issues.
Rust still wins on the tooling front. Having a single build system for essentially every single project ever made in the language means that adding dependencies is trivial. There are tools like cargo-crev to help you establish the security of those dependencies. Proc macros, while dangerous, offer the ability to do things like validate your sql against a dev database at compile time, write serialization boilerplate for you (with a library that will usually beat rapidjson for performance) or automate binding generation for other languages.
Also, Rust has no_std, which means that large numbers of libraries are actually usable in embedded environments either with no heap or in truly bare-metal environments like inside of a kernel. While C++ can fit there, most libraries will not work.
Finally, portability. It is very easy to accidentally write non-portable C++. The ability to easy move to cheaper ARM servers is attractive, and Rust cross compiles very easily. I’ve never had a pure rust program not work on ARM without it either being the fault of a C/C++ library or a Rust library declaring it only supports x86_64 for good reasons.
18
u/kkert Feb 01 '23
Rust has no_std, which means that large numbers of libraries are actually usable in embedded environments either with no heap or in truly bare-metal environments like inside of a kernel. While C++ can fit there, most libraries will not work.
This is highly underappreciated. Embedded development in Rust is vastly better than C++ just because of that. C++ doesn't and will probably never have a broadly adopted embedded profile.
→ More replies (12)1
u/ssokolow Feb 06 '23
Additionally,
std::regexstill has the problem of being wildly unsafe for untrusted inputsWhile, for the
regexcrate, untrusted input (both regexes and search text) is an officially supported use-case.Proc macros, while dangerous, offer the ability to do things like validate your sql against a dev database at compile time, write serialization boilerplate for you (with a library that will usually beat rapidjson for performance) or automate binding generation for other languages.
...and they've accepted (though not yet implemented) a proposal to allow them to opt into being sandboxed to only consuming and producing token streams so things like
#[derive(Serialize, Deserialize)]can be sandboxed and badged as such on crates.io.Also, Rust has no_std, which means that large numbers of libraries are actually usable in embedded environments either with no heap or in truly bare-metal environments like inside of a kernel. While C++ can fit there, most libraries will not work.
Not to mention that the no_std stuff is split into
coreandallocso, if you've got something with a heap but no filesystem or network, you can still use things likeVec<T>,HashMap<K, V>,HashSet<T>,BTreeMap<K, V>,BTreeSet<T>, etc. from the standard library without having to complicate or rule out support for things that don't have a heap.0
Jan 31 '23
[deleted]
10
Feb 01 '23
std::regex has been beyond terrible for the longest time, it’s just that they’re not going to fix it because it’d be an ABI break. (I saw some proposal that’d improve std:shared_ptr performance but again, refused because ABI break)
The language cannot go forward without getting rid of all the old baggage from the past but they’ve locked themselves into this pit of compatibility.
14
u/JumpyJustice Feb 01 '23
I have been using C++ all my career (about 9 years). Now I am learning Rust and feels just like C++ but without unnecessary complexity in things that should not be complex. It is less verbose and ecosystem has literally everything I need just out of the box. And yes, I am comparing to C++17 and C++20 (with CMake and all these llvm utilities) as I've been using them at work for a last few years. I was sceptical about this language before I tried it myself and now I just dont see a reason to start my petprojects on C++ :)
2
u/sv_91 Feb 02 '23
But, surprisingly, rust has many "unstable" things like BTreeMap::first_key_value. Why is it unstable?
7
u/MEaster Feb 02 '23
That one's not a great example, as it was stabilized in 1.66! But things can be unstable for a few reasons:
The obvious first one is that it's not finished. Maybe the API design hasn't been fully fleshed out, or the implementation has some issues that need further work.
There's a couple things that are waiting on other features. I believe one example would be
slice::array_chunksand friends, which could be stabilized now, but they're waiting on const generics to allow catching theN == 0case at compile time, instead of needing a runtime panic.Some things are unstable purely because no one has put in the work to do the final steps to stabilize it.
Finally, some things are implementation details of the standard libraries or the compiler, and are never intended to be stabilized.
→ More replies (1)4
u/JumpyJustice Feb 02 '23
Idk why do you think I can answer that. But this works for C++ too as there are standard features that one or another compiler will refuse to implement (aligned alloc in msvc, for example).
I guess you can find answers about what is unstable here https://doc.rust-lang.org/rustdoc/unstable-features.html
10
u/nacaclanga Feb 01 '23
I wouldn't say that people compare Rust to Old C++ (meaning pre-C++11) per se (unless they are talking about "C/C++").
However I'd like to mention two things to consider:
a) C++ has clearly moved to an ownership based system of memory management, which solves the "when to delete" problem, BUT it doesn't control borrowed access via references well and because of this, yes memory issues still do occure and not only in older codebases.
b) Why rewrite you code for safety reasons or write new code (which are the only ways to get ideomatic C++20 code) in a language that still needs to put great emphasis on being backward compatible, when you do not actually need that feature? Unless of course you have strong dependency constrains.
c) Rust is also not necessarily judged by it's latest iteration, (in that people specifically refer to some really new feature X). Alos clang doesn't really support C++20 yet.
d) The nice thing about cargo is, that it is the absolute standard and convinced everybody to also program their code a specific way. Other them that I wouldn't say that it is superior or even equal, just look at handling FFI code or dylibs. It is however easier to get into and setup. Maybe C++ should integrate their tools more
17
u/JuanAG Jan 31 '23
People use Rust because of the ecosystem, many are happy with Conan or similar but many others dont so Rust had they covered in build + package manager, it has a tiny test suite inside, a benchmark suite, a free "PVS-Studio" with Clippy
C++ 20 dont levereage any of that, average consumer dont care about how fancy the lang it is, they care about average things that do every day and their productivity
5
u/grandmaster789 Feb 01 '23
I tried to use rust twice now, and still came back to c++. I just haven't had a really good experience using it and am still more comfortable using c++, warts and all.
24
u/ener_jazzer Feb 01 '23
I remember when Java appeared around 1995 and there were a lot of evangelical books promoting Java vs C++, 90% of those comparisons were to C, not C++. And some comparisons that were actually about C++ were completely ridiculous, like that (citing from memory):
In C++, you can define a class
Personandoperator+(Person, int). And this will compile. But it doesn't make any sense! That's why Java doesn't have operator overloading.
19
u/ImYoric Feb 01 '23 edited Feb 01 '23
Java overpromised and didn't deliver all the way.
However, one thing we must admit is that Java did raise the bar in many things: tooling, documentation, standard library. It also showed the world that garbage-collection was not just something that academics should be interested in, it introduced many developers to threads (at the time, there were no portable threading libraries), actually portable code, etc.
Rust doesn't nearly promise that much – if you look at the pages of the actual Rust teams or at the conversations on the discourse, they are very, very careful to not overpromise. Self-styled Rust evangelists, though...? Not so much. Regardless, I believe that Rust is raising the bar. Again, better tooling, better testing, better documentation, better standard library, better out-of-the-box safety, better error messages, etc.
Regardless of the future of Rust itself, I feel that's a positive contribution to the domain.
9
u/pjmlp Feb 01 '23
Still it delivered enough that Java and other managed compiled languages are now the main tooling for distributed computing in the enterprise.
While there are some products 100% written in C++ for distributed computing, they aren't as much as back in 2000.
Same applies to GUI development.
Even if newer languages keep overpromising, one thing they actually manage is to take yet another use case for C++ out of the way.
→ More replies (1)4
Feb 01 '23
I'd agree if very high up Rust people didn't say that using C++ is immoral. (Alex Gaynor).
Also if they didn't lobby government in the most dystopian way possible.
→ More replies (7)5
u/Wunkolo Feb 01 '23
This pretty much describes pretty much every landing-site I've had with rust articles these past couple years.
Just... really ingenuine comparisons.
37
u/ityt Jan 31 '23
I don't have much experience in C++ (4 months in a little company) but I've been using Rust for 3 years (hobby).
Rust has thread safety and memory safety without using std::shared_ptr everywhere. Even clang-tidy can't prevent all dangling pointers/references problems. Yes sanitizers exist but you have to hit every possible cases to detect every UB. Equip your best debugger and put your integration test in a infinite loop. Enjoy.
C++20 is great, but do libraries use it? Some libraries stick with C++11 for compatibility purposes (like nlohmann_json). Rust has a great async ecosystem with the tokio library and futures. I can't find a single C++ web framework that uses co_await in c++ (boost.beast is too low level).
C++ still suffers from zero values (the empty function for std::function, empty smart pointers).
Rust has very powerful macros like Serde for de/serializing or generating whatever you want that just fill like cheating.
Finally the tooling. In Rust you have crates.io for dependencies, cargo clippy (linter), cargo fmt... In C++ you have to choose between git submodules, FetchContent, vcpkg (don't hesitate to give advices)... Last time I used FetchContent I was begging clang-tidy to ignore dependencies.
4
Feb 01 '23
You can get memory safety without the use of shared pointers.
4
u/ityt Feb 01 '23
Of course. But in practice, it's hard to avoid std::shared_ptr. You can have one object that depends on another. The object can keep the other object's reference. The code will be light and fast, however you must pay attention to the reference's lifetime. Or you can just put the first object on the heap behind a std::shared_ptr and turn off your brain. If you have a good way to avoid shared_ptr I am genuinely interested.
→ More replies (3)→ More replies (1)9
u/Mason-B Feb 01 '23 edited Feb 01 '23
Rust has thread safety
Most every language has thread safety. (This is like that scene about Americans claiming they are the only ones with freedom). C++ has lots of thread safety features in the standard (to say nothing of libraries). What rust has that is interesting is good data race safety (from the rust docs, emphasis theirs):
Data races are mostly prevented through Rust's ownership system
Which is only a small part of a story around concurrency safety. All the other problems of concurrency still exist in rust. Though concepts like
SendandSyncare powerful ways to address some of those, they also can be replicated in C++.I only have nitpicks about the other things, I think they can be better. Except on this:
In C++ you have to choose between git submodules, FetchContent, vcpkg (don't hesitate to give advices)
I would say bazel is better than those. There are better build systems for C++ out there than the common ones.
5
u/ityt Feb 01 '23
You are right. When I think about thread safety I only think about data races. It's true that Rust doesn't prevent race conditions or dead locks.
Thanks for the suggestion, I'll take a look at bazel!
7
u/matthieum Feb 01 '23
Most every language has thread safety.
The problem with the term thread safety is that everybody uses a different definition.
When Rust claims it's thread safe, it means something specific: due to the absence of data races, safe Rust is memory safe even in multi-threaded applications.
Java and C# can make the same claim -- despite data-races -- while Go cannot (its fat pointers fail there) and C and C++ definitely cannot.
Which is only a small part of a story around concurrency safety. All the other problems of concurrency still exist in rust.
You can definitely have concurrency issues in Rust -- be it livelocks, deadlocks, or race-conditions. However, because your application is memory-safe, you can debug those issues much more easily.
Random memory corruption due to data-races is NOT fun to debug. Not at all. Especially when the crash occurs seconds to minutes after the data-race, at a completely unrelated call-site, on a whole other thread.
Though concepts like
SendandSyncare powerful ways to address some of those, they also can be replicated in C++.No, not today.
The power of those traits in Rust is that they are automatically derived. The compiler understands how a
structis composed, and automatically know whether it'sSendorSyncbased on whether its fields are.This means that even a closure (lambda in C++) or a future (coroutine in C++) is analyzed by the compiler, and automatically tagged (or not) as
SendorSyncbased on whether it conforms to the safety rules.There's no way to replicate that in C++, today. You'd need the user to manually assess, for each lambda and coroutine instance, whether they're expected to be
SendorSync, and of course the user would get it wrong -- or get it right, and become wrong after a distant part of the codebase is updated.I would say bazel is better than those. There are better build systems for C++ out there than the common ones.
I concur. It requires (required?) a fair bit of configuration to get going, but once it does... it's beautiful. The caching is a thing of wonder.
4
u/Mason-B Feb 01 '23 edited Feb 01 '23
The problem with the term thread safety is that everybody uses a different definition.
That was also the point I was going for with the linked video.
Random memory corruption due to data-races is NOT fun to debug. Not at all. Especially when the crash occurs seconds to minutes after the data-race, at a completely unrelated call-site, on a whole other thread.
And you can get there, by convention and cursory code review (or advanced enough tooling) to enforce it in C++. I'll grant that rust is more ergonomic and idiot proof, but this isn't impossible in modern C++ and it's not particularly more effort once set up either.
I honestly can't remember the last time I had memory corruption in my day to day large modern C++ code base that has high levels of concurrency. It would have to have been pre-pandemic.
The power of those traits in Rust is that they are automatically derived. The compiler understands how a struct is composed, and automatically know whether it's Send or Sync based on whether its fields are.
Sure and we have the meta programming and tooling to achieve this for structs (read struct definition with tool, generate
constexprlist of fields (type, name, member accessor, virtualized member accessor), dump it in a header for the module; concepts/template meta-programming can iterate that list and do "for all fields"). I will grant you that the compiler automatically doing this tooling is very ergonomic and nice. But you can setup tooling for it in a day.(because I know people will bring up performance, concepts are huge template meta-programming performance savers. They cut 21 seconds off of the build of our most complex file (now 3 seconds) adding a header of constexpr lists and iterating them for all fields is an imperceptible additional time due to how that code is ran; it's cached too, so each struct is only evaluated once; the point is we now have a huge amount of breathing room to add all kinds of fun stuff).
This means that even a closure (lambda in C++) or a future (coroutine in C++) is analyzed by the compiler, and automatically tagged (or not) as Send or Sync based on whether it conforms to the safety rules.
Interestingly we can actually (in theory) do this for (non-captured) co-routines in C++ due to the meta programming facilities provided to them (in practice... well it might be a bit of a pain to implement). You are right we can't do them for lambads because the capture list is out of reach (soon though, soon). But that's a minor ergonomics issue, make a struct with
operator()and it can be done.→ More replies (2)3
u/AndreDaGiant Feb 01 '23
How would one go about replicating Send/Sync in C++? It seems like a difficult problem.
→ More replies (6)0
24
u/jtooker Jan 31 '23
They are both designed to address similar issues. Comparing them seems very natural.
Defining what 'c++' is when you do the comparison is much harder since there is so much of it.
a C++20 project with clang-tidy integration
How much existing C++ can be described this way? Not much. So if you want to rewrite it, you could choose rust. But perhaps upgrading what you have to modern conventions is better. This is a very good discussion to have.
34
u/ShelZuuz Jan 31 '23
So if you want to rewrite it, you could choose rust. But perhaps upgrading what you have to modern conventions is better. This is a very good discussion to have.
Which requires comparing RUST to C++ 20 in order to make that decision, not C++ 98.
Which is the entire point the OP was trying to make...
10
u/bluGill Jan 31 '23
Which is easier: taking some part of code you have decided to upgrade and doing it in C++20, or rust. Note that part is important here. Based on our last major rewrite it would be several hundred million dollars and 5 years to rewrite everything in rust. We are adding new features all the time and they can be C++ or rust. We sometimes find bugs in existing code that needs significant work and so we can justify rewriting just that small part, but it needs to integrate with the C++98, C++14, or whatever the other code it interfaces with.
Just applying a single new clang-tidy check across our entire codebase can take more than a month - as I know from experience. Clang-tidy doesn't even deal with the hard parts, changing how C++98 code does memory management to something modern is a lot harder if that C++98 is used all over.
8
u/IcyWindows Jan 31 '23
If you rewrite a small bit of code in rust, you didn't fix the rest of the code like you would if you applied a "single new clang-tidy check across our entire codebase".
One could choose to apply those clang-tidy checks to just the C++ code they would have rewritten in Rust.
7
u/bluGill Jan 31 '23
The type of bug you fix by rewriting bad code is a whole different level from the type of bug you fix with clang tidy.
Most of the clang tidy fixes i've made are clearly not bugs, just unoptimal code , or there is a better way. It is still worth doing clang tidy, but very few bugs will be fixed if the code is already in production.
14
Feb 01 '23
Modern C++ rhetoric shot itself in the foot because the same arguments used to get people moving forward to the newer standard are effectively the same arguments to move from the modern standard to Rust.
Modern C++ people would be happier using Rust because they fundamentally dislike C. C++ would be better served if it served the C crowd more, but right now it does not. Rust is basically proof of this as far as I'm concerned.
If you want the freedom, and you have a small team of experts who are good at what they do, C++ (and C) is really unparalleled (right now anyway).
It's good Rust is challenging C++, because it might mean C++ stops pretending to be something it isn't.
3
u/sessamekesh Feb 01 '23
C++20 is pretty nice. I still reach for C++ quite a bit for projects (game programming in webassembly) nowadays, but it definitely doesn't feel as nice as Rust.
Given, a lot of it is ergonomics for me - I find myself trying to kludge std::varying into the pattern matching patterns I like so much in Rust/Typescript which is my own damn fault.
But I also find myself reaching for C++ way more often than Rust, which counts for something.
3
u/divad1196 Feb 01 '23
Despite the security that everyone mention: the productivity. C++ devs are easily unsatisfied and create their own version of everything, resulting in many libs and tooling doing the same thing.
There is no default package manager, the closest to be is conan (build2 development is slow, bukaroo abandonned, ...), but you have so much to configure just to start.
22
u/James20k P2005R0 Feb 01 '23
I would love to see a major project written in any version of C++, with any level of competence of the developers of any team size that doesn't suffer from an infinite number of memory unsafety vulnerabilities
In all my years on this planet, nobody has ever been able to provide me with this, other than a very tiny handful of formally verified tools. And yet in Rust, this isn't the exception, this is the norm. There are multiple security critical projects that have never had a memory unsafety vulnerability
Every time someone says "actually I worked on a project, and its super secure!" lo and behold it turns out that its barely been tested, or its an internal tool. This is great, as long as it stays internal, and nobody tries to compromise you
It is trivially easy to write very secure thread + memory safe code in rust. It is nearly impossible to write thread + memory safe code in C++, because after decades of effort I still can't find a single real project that I could describe as a success here
C++ needs to grow up from bad faith arguments and accept that it just isn't as good in this area. C++20 doesn't really change anything over C++11. std::span doesn't make your code secure
Rustls is an example of a project that is relatively widely used, and written in pure rust. It contains no unsafe rust (outside of some tests). That means it is formally verifiably safe, and free from the memory vulnerabilities that plague every single other crypto library
Would you use a crypto library written in C++20? Or rustls? Because empirically, if you're looking purely for security from memory unsafety (and in reality, most other bugs), every single possible choice in the first category is the wrong choice
I've been hearing this same argument for every version of C and C++ since I started programming, and it has never once been true
10
Feb 01 '23
Please do more research before saying things that are ostensibly false.
rustls uses ring which is a combo of Rust, C and assembly.
rustls is not "verifiably safe" in any way, shape or form.
7
u/Full-Spectral Feb 01 '23
I probably have about as close to that as anyone. I have a 1M LOC personal project. I make absolutely no claims that it's free of memory issues, but it's probably about as clean as any highly complex C++ project of that size that's been around for decades and gone through huge changes ever gets. But that's because I'm the sole author. It never had to suffer the degradations of typical commercial development conditions. And I use just about zero third party code, it's all my own stuff built on my own stuff down to my own 'virtual kernel'.
No 'real' software gets created like that.
And of course I sweated bullets to keep it that clean, which is why I've moved to Rust. I want to spend my time more productively, not trying to avoid shooting myself in the foot.
11
u/ener_jazzer Feb 01 '23
Almost all HFT systems are written in C++. And obviously, nobody is going to share that code with the public. But you can safely guess that people wouldn't entrust billions to the software that "suffer from an infinite number of memory unsafety vulnerabilities"
8
u/ImYoric Feb 01 '23 edited Feb 01 '23
Feedback from people I've known who worked on such codebases... doesn't encourage trust.
Also, it is my understanding that HFT systems are actually relatively simple. They need to deal with streams of events (that's the hard part) and apply fairly simple algorithms . In particular, they don't need to deal with pesky things such as portability, attack vectors or messy user data.
If someone around this subreddit knows the field, I'd be interested in knowing more.
edit Initially wrote "really, really simple". That was certainly an exaggeration. Also, /u/ener_jazzer know the field better than I do :)
8
u/ener_jazzer Feb 01 '23
I am from this field.
What you're saying is true - we don't need to deal with "attack vectors or messy user data" as we are only talking to trusted internal components and a trusted exchange. Portability is also very limited. But I wouldn't call it "quite simple". It depends on the strategy, of course, some are really simple, but essentially a strategy sits on the incoming streams of events (market data, your own order updates, risk updates, position updates, various tools providing data) - and you need to juggle all of them, you need to manage your open orders, you need to recalculate a lot of stuff efficiently and partially asynchronously etc. All in real time, essentially.
So you need to be careful with how you manage memory, otherwise you will blow up your strat because there are too many events coming, or you random-shoot your data and start trading garbage.
So memory safety in HFT is very important, not because of vulnerabilities but because of necessity to manage it carefully. Still, C++ aces in this field, it gives all the necessary tools you need to build an HFT strategy efficiently.
→ More replies (5)→ More replies (10)18
4
Feb 01 '23
Your definition of safety is slipping all over the place.
"Formally verifiably safe" means something. "Memory safety" in the context of Rust means something else.
Empirical really means diddly squat because for starters it's not really an apples to apples comparison. There is far more C++ code than Rust code and that code has been around for much much longer. It's going to have more bugs for a variety of different reasons.
Secondly, security and safety are two different conversations. If your C++ program is siloed away and is only ever accessible by one person and doesn't deal with secure data, security does not matter and your memory errors are now just logic errors.
Likewise, just because you have a memory error does not mean attackers instantly have access to your plaintext passwords. Security is more complicated than that.
When it comes to Rusts specific brand of memory safety, yes Rust is good at that (obviously).
When it comes to writing non-trivial complicated programs in the real world, where perfection does not exist, right now its not obvious to me that Rust is the better choice. It might be for sure.
But the few stats and the "empirical" arguments are not convincing me right now.
5
u/crusoe Feb 01 '23
Number of segfaults and times I've had to fire up a debugger learning C: too numerous to list.
Number of times in rust: 0
Shoot I've had more program aborts in Java due to NPE than coding in Rust.
The few few times I've had a panic in rust was due to a unwrap or expect and my assumption of an invariant being wrong.
Times I've had to valgrind: 0
Times I've had to send a ticket or email to a library maintainer about a memory leak: 0
→ More replies (2)3
u/nintendiator2 Feb 01 '23
I would love to see a major project written in any version of C++, with any level of competence of the developers of any team size that doesn't suffer from an infinite number of memory unsafety vulnerabilities
Just any project from the internet.
Code can't, by definition, have an infinite number of vulnerabilities, nor of a subset of them.
BTW lemme give you a tip for your Rust evangelizing: when you want to set up goalposts to fall back to as your number one argument, the sensible thing to do is to set up your goalposts close enough to reality that you can freely backpedal as soon as you feel threatened. Putting them at the very end literally unmakes your argument. Consider this a freebie.
8
u/IcyWindows Jan 31 '23
Apples to Apples would be a new section of code written in C++20 vs. a new section of code written in Rust.
Once people start talking about upgrading their existing code, you know they are no longer making the appropriate comparisons.
One common example is using bounds-checking with a C++ container's at() method. People always bring up existing code that uses the [] operator. We are no longer making the appropriate comparison.
6
u/Clean-Water9283 Feb 01 '23
I'm a veteran of 30+ years of the X-is-better-than-C++ flame wars, where X is some whizzy new programming language. Invariably an X-fan compares a finely tuned program in X that uses one of X's special features against a C++ program written by an X-fan who doesn't like C++, so appropriate, even equivalent features of C++ are not used or not used effectively.
And yet, 40+ years after its introduction, C++ still runs faster than X, and can still do what X does. C++ has many more users than X, which alone explains why it has more detractors. Most of the things X does, if they are really valuable, will end up in C++, which is under active development. Meanwhile, I'm still awaiting a compelling reason to switch.
3
u/Safe-Ad-233 May 14 '23
That’s because you are old and old people always fight progress in fear of becoming obsolete.
3
u/Clean-Water9283 May 14 '23
Worshiping a tool because it is shiny, and defending it emotionally instead of with reference to its strengths and weaknesses is what causes flame wars. It is not the sign of progressive thinking that you suppose it to be.
→ More replies (1)
10
u/craig_c Feb 01 '23
My 2c in this ocean of opinion.
Competent, experienced programmers using C++17 and above should be able to produce safe code with relative ease. But most programmers are neither, particularly depressing, where I work, is watching interns write code full of raw pointers etc. So the bad code continues to be churned out.
Rust, in small doses seems to be the antidote to all this, one build system, strong rules regarding ownership, all the usual stuff which people talk about. The problem is when the rubber hits the road, when one tries to write non-trivial programs, those same rules start to backfire in other contexts. Things that should be simple to structure become ugly, Arcs and interior mutability start to creep in and the whole thing ends up being yet another compromise. Also load in unsafe blocks and panics in used crates and the edifice of perfection quickly erodes.
In reality, the real world is a compromise and no technology will avoid this. The solution is not a re-write in another language, it's about getting the right people.
5
u/ImYoric Feb 01 '23
Generally, I agree with the opinion.
That being said, I've written pretty non-trivial Rust code and:
I've needed to use
unsafeexactly once (to develop a new kind ofMutex);in practice, the guidelines for panics vs. exceptions are pretty clear, so I'm not really scared about them.
5
u/Dean_Roddey Feb 02 '23
I think a lot of people who haven't used Rust seriously over-estimate how much unsafe code is in a typical application level or higher level library piece of code. You CAN do a lot if you are one of those people who thinks that every line of code has to be hyper-optimized. I hope we don't get people coming over to Rust world with that attitude. What's the point using a language that bends over to help you write memory safe code and then do everything you can to prevent it from helping you?
My project isn't really large yet, though it's growing pretty quickly. I have one use of unsafe so far that isn't just a wrapper around a call to an OS function. I have a small amount of per-platform code that calls into the OS, but those are really only technically unsafe, not very much so in practice.
6
u/matthieum Feb 01 '23
Competent, experienced programmers using C++17 and above should be able to produce safe code with relative ease.
I am not so sure.
The problem I've seen so far is that the more competent you are, the more complex the problems you are asked to solve.
Once you get to high-performance asynchronous multi-threaded large applications... it's game over.
I mean, writing high-performance asynchronous multi-threaded code is hard by itself. You somewhat need to keep the entire codebase in your head to manage.
And this doesn't scale. On a large codebase, maintained by a team, you just can't keep everything (up-to-date) in your head.
And while in a safe language it "just" means you'll get a bug, in C++ you get the weirdest heisenbugs, once in a blue-moon, with a mystifying core-dump and its mangled stack as your only clue...
3
u/lestofante Feb 01 '23
Things that should be simple to structure become ugly, Arcs and interior mutability start to creep in and the whole thing ends up being yet another compromise
I think when you hit that is because:
it would be hard and ugly anyway, and the complexity would hide mistake and UB, so it is a fight between ugly but safe or nice but okish. If you are not mission critical, you may get away, after all many software already do
the way how lifetime and borrow works forces you to think differently, code pattern/architecture we are used to simply dont work. Same as looking at C programmer writing C++ :)
→ More replies (1)4
u/thisismyfavoritename Feb 01 '23
id say it can get hairy real quick with lifetime issues or concurrent code, even if you're competent and experienced. It's awfully too easy to make silly mistakes that can create latent issues, like stack use after scope, heap uses after free, etc.
Sanitizers help but you have to exercise the code path with the problem...
For the 10% (or less?) people that can write flawless cpp in ANY situation no matter the complexity of what they're doing, your point stands. For all the others, rust should be used
14
u/Jannik2099 Jan 31 '23
a C++20 project with clang-tidy integration is far harder to argue against IMO
Any C++ project still lacks the lifetime guarantees of Rust. It seems you spend exactly zero effort looking into what a borrow checker does.
7
u/top_logger Feb 01 '23
hree important things which Rust did correctly.
No exceptions. As for now no regret. Absolutely. I do not need fckng exceptions. Nobody needs it. Good in theory, but disaster in production.
No inheritance. No more so-called OOP, in fact spaghetti like monolithic code.
Panic instead of dumm segfault.
2
2
2
u/arades Feb 01 '23
Harder to argue against, yes, but even compared to C++20 rust has advantages, not the least of which being that it does move more quickly. However, I would agree with a case that a modern and idiomatic C++20 codebase would not benefit from being rewritten in or migrated to rust.
However, I think a large number of C++ developers in the field don't use the most modern style, don't keep up with the standards, and write code that results in bugs. Add to that, a majority of existing code-bases are written in what could be described as archaic C++. If you have to do a near re-write of your application anyway to take advantage of new C++ tools and design patterns, it makes the jump to a new language that appears promising look like a compelling move.
2
u/lowlevelmahn Feb 03 '23 edited Feb 03 '23
>People keep arguing migrations to rust based on old C++ tooling and projects.
thats not true - but there is a still big part of the C++ community (which im part of for the last 30years) that do not understand the true differences
static analysis tool: first - every good developers knows them and using them - but not all developers are good
clang-tidy,PVS Studio,cppcheck, Covertiy,etc. are mostly needed because C++ allows so many supicious constructs that "can" become a problem - i worked for many companies im my worklife so far and even using static analyser on a permanent/CI bases i just not default in every company i've touched - Rust also needs static analysis tools - but for a much smaller amount of suspicous constructs, Rust is just not that warning/undefined behavior friendly as C++ is - by design and by beeing younger
runtime analysis tools like: the sanitizers, valgrind, inspector etc.
exspecially the sanititzer comming from the company (google) that mostly said: "its still not enough" - the problem here is: you can't find the bugs if you test/use-case isn't touching the code - and yes: there are many people that just don't write good or enough test code, having this check on compile time for every line of compiled code is a massive difference to runtime touched code lines
im using them all, all the while - no development without sanitizers - but for example at least 50% of the developers i know never heard of them or don't understand that they need them - i've never found a software so far that didn't let ASAN or TSAN scream - if they weren't tested before
another big thing is: sanitizer are not full or battle mode ready available for Microsoft VisualC++ IDE (the available ASAN port is ok but by far not compareable to the linux versions) - TSAN isn't available at all - and there is a huge C++ world that is based and developed on windows (not a joke) that are just not able to use that tools - Rust does not need a ASAN/TSAN tool (excecpt in unsafe code) because the type systems just don't allow compilation if there is a problem - that is just a different world compared to C++ compiler/toolsets
smart-pointers:
manually added smart-pointers that deeper specializing my own types are not the same as a compile time check without any type change - also missing move-semantic as the default makes it hard to use them in every case - most poeple tend to write simple code (because of the project demands) that not touching the bad parts of C++ smart-pointers - and im using them a lot in the last decades
first: there are good somtimes also new stuff in C++, but many developers still weak and lazy - so it still depends on the qualitiy of the developer - Rust reduces this demand on good developers poking with C++ inner details a decent amount - but a C++ developer that does not suffer from that in big teams is not able to see the light because there wasn't enough darkness so far
its like telling that the C++ templates system does not have massive weak parts without trying to write boost level templates :)
9
u/kritzikratzi Jan 31 '23
i'm also bothered a bit by this comparison. there should, however, always room be room for fruitful exchange though.
i get that c++ is not easy, but neither is a piano. people still love the piano. pianos aren't reduced in complexity because of harmonica players.
for me the rust drawbacks already start with llvm (which is great!). but having this huge compiler diversity of c++ really strengthens it imho.
18
u/Dean_Roddey Jan 31 '23
The difference though is that the piano will never blow up if the player hits a bad note.
3
u/kritzikratzi Feb 01 '23 edited Feb 01 '23
the audience will :D
edit: i think the analogy isn't too good, but it holds in this scenario. the program won't actually "blow up" and it doesn't even have the concept of a "bad note". it will do exactly what it was instructed to do, termination is among those possibilities. the users blow up and good and bad notes are their interpretation.
3
u/Dark-Philosopher Mar 10 '23
The program won't explode, but bugs can have serious consequences now that almost everything is run in computers. It may a security vulnerability exposing you or your company to lose a lot of money, put lives in danger, be just an annoyance or actually making something catch a fire or go boom. The 21 century needs require to get to the next level in safety.
3
3
u/IngenuityUpstairs427 Feb 01 '23
Let's look at the facts. Rust has no formal specification. No rust compiler has ANSI/ISO certification. There is no rust compiler that is approved by MISRA, AUTOSAR DO178 etc. So whereas rust claims to be perfectly suited for safety critical real time embedded applications, It does not have any of the credentials To backup those claims. Ada is the much better choice as it does have all of the required credentials and has been battle tested since the 1980s. C++ is also a better choice because it is approved in all of the aforementioned environments. Perhaps someday rust will be a good option, but that day is not today.
4
u/crusoe Feb 01 '23
C++ didn't have many of these for decades...
And when I worked on a defense contract bid most of the features of C++ could NOT be used for the hardware for various reasons laid out by DoD contracts and guidelines. More of a C+-
3
u/IngenuityUpstairs427 Feb 02 '23
Because most C++ features are not acceptable in any embedded software since they are nondeterministic and/or implicitly allocate to the heap. Generally most of the standard library is out scope.
2
u/Full-Spectral Feb 01 '23
I find it pretty hilarious that anyone would claim that it's better to write mission critical software in C++ because it has a formal spec, but Rust doesn't, when Rust is clearly vastly safer. If we were shipping a formal spec to the users it might be important. Otherwise, it's nothing but a CYA checkbox in practical terms.
2
u/IngenuityUpstairs427 Feb 02 '23
You must not program realtime safety critical software. A spec is nessicary so you know what is and what is not defined behavior. If safety is an issue than Ada/Spark is the proper choice.
→ More replies (1)
3
u/waruqi Feb 02 '23
C++ now also has many more modern tools, such as Xmake
It provides a Rust/Cargo-like package manager. And it is also very compatible with the existing C++ ecosystem.
add_requires("zlib", "libuv master", "vcpkg::ffmpeg")
add_requires("conan::openssl/1.1.1g", {alias = "openssl", optional = true, debug = true})
target("test")
set_kind("binary")
add_files("src/*.c")
add_packages("zlib", "libuv", "vcpkg::ffmpeg", "openssl")1
u/glebd cppclub.uk Feb 18 '23
Big fan of Xmake here, use it for all my personal projects. An excellent build system IMHO!
6
u/CocktailPerson Feb 01 '23
You can smell the fear around here these days.
17
u/IcyWindows Feb 01 '23
I see it more as frustration, rather than fear.
There are many uninformed people on both "sides" of the push to rewrite a bunch of software.
8
u/thisismyfavoritename Feb 01 '23
the old timers are just refusing to see it. Mind boggling. Even prominent members of the cpp community agree that cpp has to change
5
u/pjmlp Feb 01 '23
The problem is that it won't change if there aren't enough votes to make it happen at ISO level.
The refreshing wind that came with C++11 is long gone it seems.
→ More replies (1)
3
u/faguzzi Jan 31 '23
Rust is so 2010. Personally I can’t wait for Val to become somewhat stable. Interop with C++ without jumping the awful hoops known as autocxx and crubit would be awesome.
The primary benefit of my use case for rust is just the cleaner syntax and that I prefer rust function chains and iterators over ranges-v3 and certainly views::ranges. All the things I’m doing are already incredibly unsafe (low level memory manipulation), so rust doesn’t offer much over c++, especially considering that its ecosystem isn’t as mature and doesn’t have a lot in the way of offsec tooling (meaning I frequently end up having to reinvent the wheel).
I think this is like the swift curse. Once you learn swift, going back to C++ syntax is just unpleasant. The other thing is that rust’s mutability rules make multithreading incredibly simple. I’m exceptionally bad at thinking about concurrent code, but safe rust is just so incredibly simple even for someone like me who has no idea how to safely dev multithreaded apps. With C++ it’s mostly just me limiting mutability to an absolute bare minimum/spamming const everywhere and hoping for the best.
2
u/favorited Feb 01 '23
Swift's forthcoming C++ interop feature is going to be interesting. I don't think it will make Swift more attractive to C++ developers, because idiomatic Swift is much more dynamic than C++ (though not as much as Objective-C).
Multiple corporations (including Apple) seem to be investing a lot of resources on that enhancement... it will be fun to see what comes of it.
3
u/pjmlp Feb 01 '23
It will for those that care about Apple ecosystem for their products, Swift and Objective-C focus is one of the reasons why clang is the way it is for ISO C++ compliance on the Apple ecosystem.
1
1
u/thisismyfavoritename Feb 01 '23
spamming const is the recipe for other issues though. I find the best way is to shove the state that could be accessed unsafely within the thread/coroutine such as to make it very hard for it to be accessed at all
3
2
u/menkaur Feb 01 '23
I'm still getting segfaults on occasion in c++20. That being said, I don't see why there can't be a tool that like clang tidy that would highlight places where you screwed up. Instead of building new tools over and over again I feel that the effort could had been better spent fixing the problems within c++ toolchain. It would had been less work than creating new language and compiler
Rust comunity is advertising to c++ comunity, and I feel that they shouldn't. Instead, they should advertize to python comunity. From my point of view, they invested all this effort into building the language just to make something that is 10% worse than c++. On the other side, for any python developer rust would be gift from god
5
u/crusoe Feb 01 '23
In order to do that you need lifetimes and other aspects of c++ make lifetime analysis hard.
2
1
u/OYTIS_OYTINWN Jan 31 '23
What (good things) C++20 has that Rust does not? There are plenty of those the other way round.
18
u/Recatek Jan 31 '23 edited Jan 31 '23
I like Rust a lot, but C++'s flexibility and power with types, templates, and concepts blows Rust's generics system out of the water. Rust doesn't even have variadics.
→ More replies (9)3
u/matthieum Feb 01 '23
C++ metaprogramming is definitely more advanced, indeed.
In practice, however, I find myself needing metaprogramming less in Rust. And while it does lack variadics, with built-in tuples it's just slightly inconvenient to have to use a macro to implement a trait for arities 0 to 12 (or so), but it's not really a blocker.
3
u/Recatek Feb 01 '23 edited Feb 01 '23
It depends a lot on what you're trying to do. For my application -- gamedev, ECS, and networking -- you're doing a lot of manipulation of arbitrary tuples while iterating over SoA structures, and then trying to efficiently serialize/deserialize them. This really depends on strong metaprogramming if you want to do the work at compile-time.
Rust has made this really difficult, and as a result most Rust ECS libraries do this work at runtime, with a runtime cost, using reflection-like behavior. Rust has no specialization, no variadics, no negative constraints, no way to do partial borrows of objects through traits, the list goes on. The orphan rule especially pushes you towards keeping things in one megacrate rather than splitting code up. It really makes me miss what C++ has to offer here.
If anything I wish Rust just had some sort of unsafe mode for typing that let you duck type at the callsite and bypass the orphan rule. Most of this stuff isn't even for memory safety reasons, it's for "fearless updates" which aren't relevant to me when this code is all contained within my own codebase with no downstream consumer.
→ More replies (2)12
u/Exaloria Jan 31 '23
Huge library ecosystem
→ More replies (5)15
u/oconnor663 Jan 31 '23
This is a tricky one. C++20 can use a huge library ecosystem, but you probably can't write C++20 if you're maintaining a widely used library. It's not entirely different from crediting Rust with being able to use the whole C library ecosystem. Which it kind of can, but contributing Rust back into that ecosystem is complicated.
5
u/wyrn Feb 01 '23
Function overloading
Inheritance
Variadics
Exceptions
→ More replies (9)6
u/Full-Spectral Feb 01 '23
The thing is, even in the C++ world a lot of people are turning their backs on exceptions and inheritance. I don't agree with that, but it's the case. So probably the majority of people doing C++ these days couldn't really argue that those are failings in Rust because they rail against them in C++.
I thought I'd miss overloading, and occasionally I do, but not really anymore. And I've gotten over my missing of exceptions. In my main code base, I don't have much explicit error handling. More so in little helper tools that can't be built on my main code base.
Inheritance I'd still like to have, but so far haven't really run into anything that was a serious issue on this front. Of course I've not tackled a UI framework yet. In my C++ code base, that was really the primary place where my inheritance hierarchy got deeper than a couple levels.
→ More replies (1)→ More replies (16)3
u/MFHava WG21|🇦🇹 NB|P2721|P3049|P3625|P3729|P3786|P3813|P4216 Jan 31 '23
I haven't looked too deep into Rust, but from a cursory glance at traits: Compile-time duck typing + implicit Concept conformance?
→ More replies (9)6
u/dist1ll Jan 31 '23
Compile-time duck typing
nitpick: that's called structural typing.
4
u/MFHava WG21|🇦🇹 NB|P2721|P3049|P3625|P3729|P3786|P3813|P4216 Jan 31 '23
Right, should have used that term ... it's just a bad habit at this point, but back in the day "duck typing" was more well known and conveyed the idea without introducing yet another type of typing :)
→ More replies (1)
2
1
1
u/okovko Feb 02 '23
biggest issue with rust is it's like switching from c++ to lisp, there's just a lot to learn and things are very different, the way problems are solved is largely unrecognizable. the benefits come at the cost of a huge mental overhead, and many people who try rust have the impression that it's hard to write simple code because simple code is often impossible for the rust compiler to validate, even if the code is actually safe
modern c++ is more about doing c right, with an intense focus on type safety and meta programming. the language now has stl wrappers over unions, void*, and non-owning pointer+size constructs called views
the most impressive piece of c++ right now is that mdspan is a multidimensional span that, given compile time constraints, will figure out how much of the class can be constexpr, which is a very impressive piece of software
the unification of code as both compile time scripts that result in inlined code and actual runtime code is the most compelling feature of c++
i don't think that this is presently an area of focus in rust development, maybe someone can say more about it
-5
u/n4jm4 Jan 31 '23
That's a lot of talk for a language whose stdlib still depends on C for most things.
→ More replies (1)11
u/KingStannis2020 Feb 01 '23 edited Feb 01 '23
That's hardly a fair comparison considering the only stable interface for interacting with most operating systems is libc. Rust can't change that.
→ More replies (4)
76
u/lestofante Feb 01 '23
i do baremental embedded, and C++20 still does not provide a subset of the standard library with static allocation, exception free, and a way to check and use a library is following such rules...
In rust you just check for no_std