Earlier quoted context omitted.
When I looked into the history of the C++ move (which after all didn't even exist in C++ 98 when the language was first standardized) I discovered that in fact they knew nobody wants this semantic. The proposal paper doesn't even try to hide that what programmers want is the destructive move (the thing Rust has) but it argues that was too hard to do with the existing C++ design so... The more unfortunate, perhaps dis…
> When I looked into the history of the C++ move (which after all didn't even exist in C++ 98 when the language was first standardized) I discovered that in fact they knew nobody wants this semantic. The proposal paper doesn't even try to hide that what programmers want is the destructive move (the thing Rust has) but it argues that was too hard to do with the existing C++ design so... > The more unfortunate, perhaps…
The repercussions of missing an Ampersand in C++ and Rust
51–60 of 128 posts
Re: The repercussions of missing an Ampersand in C++ and Rust
#52I would never have this typo as I usually delete the copy constructor in heavy structures.
Re: The repercussions of missing an Ampersand in C++ and Rust
#53As someone who programs both C++ and Rust, without even reading the article, my own experience with typos in those languages is: Rust: Typo? Now it just doesn't compile anymore. Worst case is that the compiler does a bad job at explaining the error and you don't find it immediately. C++: Typo? Good luck. Things may now be broken in so subtle and hard to figure out ways it may haunt you till the rest of your days. But…
By the way, the project considers this a bug and accepts reports for that. In many occasions they are easy to fix. In others large refactors are needed. But being aware of the case is the necessary first step to making them better.
Re: The repercussions of missing an Ampersand in C++ and Rust
#54> There are plenty of linters and tools to detect issues like this (ex: clang-tidy can scan for unnecessary value params) Exactly, this is not an issue in any reasonable setup because static analysis catches (and fixes!) this reliably. > but evidently these issues go unnoticed until a customer complains about it or someone actually bothers to profile the code. No
This is my gripe with C++ - I have to have a CI pipeline that runs a job with clang-tidy (which is slow), jobs with asan, memsan and tsan, each running the entire test-suite, and ideally also one job for clang and one for gcc to catch all compiler warnings, then finally a job that produces optimized binaries. With Rust I have one job that runs tests and another that runs cargo build --release and I'm done...
Re: The repercussions of missing an Ampersand in C++ and Rust
#55It extends it a bit, too, with `out` meaning that the referenced argument is initialized by the function, not read.
Re: The repercussions of missing an Ampersand in C++ and Rust
#56Earlier quoted context omitted.
> The destructor already has to deal with that. That's partly true, partly circular. Because moves work this way, it's harder to make a class that doesn't have empty states, so I don't design my class to avoid empty states, so the destructor has to handle them.
Please give me an example for a class that needs to handle empty state in the destructor only because of move operations. These exist, but IME they are very rare. As soon as you have a default constructor, the destructor needs to handle the case of empty state.
The smart pointer std::unique_ptr is an example of this, sometimes people will say it's basically a boxed T, so analogous to Rust's Box but it isn't quite, it's actually equivalent to Option>. And if we don't want to allow None? Too bad, you can't express that in C++
But you're right that C++ people soldier on, there aren't many C++ types where this nonsense unavoidably gets in your face. std::variant's magic valueless_by_exception is such an example and it's not at all uncommon for C++ people to just pretend it can't happen rather than take it square on.
Re: The repercussions of missing an Ampersand in C++ and Rust
#57Note that assuming the into_iter comes from IntoIterator that’s what the for loop invokes to get an iterator from an iterable. So
for lr in LoadRequests.into_iter() {
Is completely unnecessary verbosity, for lr in LoadRequests {
Will do the exact same thing. And the stdlib will generally implement the trait with the relevant semantics on shared and unique references so for lr in LoadRequests.iter_mut()
Can generally be written for lr in &mut LoadRequests
So you rarely need to invoke these methods outside of functional pipelines if you dislike them (some prefer them for clarity / readability).Re: The repercussions of missing an Ampersand in C++ and Rust
#58Earlier quoted context omitted.
Please give me an example for a class that needs to handle empty state in the destructor only because of move operations. These exist, but IME they are very rare. As soon as you have a default constructor, the destructor needs to handle the case of empty state.
This means C++ is riddled with types that have unrelated "I'm empty" state inside them rather than this being relegated to a separate wrapper type. It's Tony's Billion Dollar Mistake but smeared across an entire ecosystem. The smart pointer std::unique_ptr is an example of this, sometimes people will say it's basically a boxed T, so analogous to Rust's Box but it isn't quite, it's actually equivalent to Option >. And…
Re: The repercussions of missing an Ampersand in C++ and Rust
#59Re: The repercussions of missing an Ampersand in C++ and Rust
#60Earlier quoted context omitted.
This was one of the most unsatisfying things about learning C++ move semantics. They only kinda move the thing, leaving this shell behind is a nightmare.
Since I use move semantics all the time, this is for me the most frustrating thing about C++ full stop. I really wish they'd fix this instead of adding all those compile-time features.