> Now in the service of minimalism we have scrollbars that consist of a thin, semi-transparent line that fades out after half a second and is nearly impossible to click and drag due to how small it is.
You can make them always on still. I've done so ever since their disappearing act started. It's not even much hidden, it's in the "Appearance" setting pane.
They're still too small and too light. Some times when a document is big enough I'm actually not able to find the scroll thumb on macOS Sequoia. Some times wiggling the scroll thumb around by scrolling slightly back and forth with my mousewheel/trackpad helps to make it visually appear, but other times I just have to give up.
"Validity" is an extremely low bar in C++, it just means operations with no preconditions are legal, which in the most general case may be limited to destruction (because non-destructive moves means destruction must always be possible).
If I call `foo(std::move(my_unique_ptr))`, I know for sure, statically, that my_unique_ptr was moved from, as part of the function call process, and I can no longer access it. Whether `foo` chooses to further move from it is irrelevant.
The only thing that is statically known here is that you’re wrong. The function I posted only moves its parameter half the time, at random. You may want to treat it as moved-from either way, but factually that’s just not what is happening.
> This is like trying to defend that you can't statically know the result of 1 + 2
It is completely unlike that. tsimionescu is asserting that they can always know statically whether `foo` will move its parameter. The function I provided is a counter-example to that assertion.
Of course the branch body always moves, that's what it's there for. That has no bearing on the argument.
That is the whole argument. Let me quote the other person: "My claim is that, if I call `foo(std::move(myObj))`, it is statically knowable if `foo` receives a copy of `myObj` or whether it is moved to it."
It is saying that for "auto pp = std::move(p);" we will know if it uses the move assign constructor or the copy assign constructor.
> Let me quote the other person: "My claim is that, if I call `foo(std::move(myObj))`, it is statically knowable if `foo` receives a copy of `myObj` or whether it is moved to it."
Yes. `foo`.
> It is saying that for "auto pp = std::move(p);" we will know if it uses the move assign constructor or the copy assign constructor.
`pp` is not `foo`. That `pp` uses a move constructor is not the subject of the debate.
You can literally take the function I posted, build a bit of scaffolding around it, and observe that whether the parameter is moved into `foo` or not is runtime behaviour: https://godbolt.org/z/jrPKhP35s
Taking a step back I think the issue is that your foo takes an rvalue reference. Which is not the case we are talking about which is whether a move or copy constructor is used when constructing the parameter of foo.
In Rust if you pass say a Box<Goose> (not a reference, the actual object) into a function foo, it's gone, function foo might do something with that boxed goose or it might not, but it's gone anyway. If a Rust function foo wanted to give you it back they'd have to return the Box<Goose>
But C++ doesn't work that way, after calling foo my_unique_ptr is guaranteed to still exist, although for an actual unique_ptr it'll now be "disengaged" if foo moved from it. It has to still exist because C++ 98 (when C++ didn't have move semantics) says my_unique_ptr always gets destroyed at the end of its scope, so newer C++ versions also destroy my_unique_ptr for consistency, and so it must still exist or that can't work.
Creating that "hollowed out" state during a "move" operation is one of the many small leaks that cost C++ performance compared to Rust.
You should not be downvoted, which you appear to be. Your comparison is both correct and interesting.
Maybe you're being too verbose for your point, and it would help readers if you summarize and narrow the argument to:
In Rust a function signature can force a move to happen at call time (by being non-reference and not Copy), but in C++ a function taking rvalue reference (&&) only signals the callee that it's safe to move if you want, as it's not an lvalue in the caller.
It's an added bonus that Rust prevents reusing the named variable in the caller after the move-call, but it's not what people seem to be confused about.
aside from what others wrote, it’s also non local - whether std::move even does anything is dependent on the signature of foo - if foo takes it by const& you may think you’ve transferred ownership when it hasn’t actually happened.
That is static though, that `foo` takes its parameter by `const&` and will thus not move it is available to the compiler (or other tooling) at compile time.
The point of contention is whether that is always the case, or whether there are situations where moving from the parameter is a runtime decision.
Look, the act of calling std::move and and calling a function taking an rvalue reference in no way invokes a move constructor or move assignment. It does not "move".
It's still just a reference, albeit an rvalue reference. std::move and the function shape is about the type system, not moving.
(Edit: amusingly, inside the callee it's an lvalue reference, even though the function signature is that it can only take rvalue references. Which is why you need std::move again to turn the lvalue into rvalue if you want to give it to another function taking rvalue reference)
I didn't reply to this thread until now because I thought you may simply be disagreeing about what "move" means (I would say move constructor or move assignment called), but the comment I replied to makes a more straightforward factually incorrect claim, that can easily be shown in godbolt.
If you mean something else, please sketch something up in godbolt to illustrate your point. But it does sound like you're confusing "moving" with rvalue references.
> it's intended for transferring of ownership versus copying data.
It's intended for transferring ownership, but what it actually does is mark the value as transferrable, whether or not the value is actually transferred is up to the callee.
> Rust’s borrow checker doesn’t actually borrow anything either
Why would it? It's called the borrow checker, not the borrower. So it checks that your borrows are valid.
std::move looks and feels like a function, but it doesn't do what it says, it makes objects movable but does never moves them (that's up to whatever is using the value afterwards). If you want something similar in Rust, Pin is a much better candidate.
Sure, but from the perspective of the code that has the move() its good to assume the value is moved at that call, which I guess was the intention of picking the name.
Usually yes, however because that's not for some resource types it can lead to less than ideal behaviour e.g. if your RAII resource is something which will get corrupted if there are two handles to it (some sort of odd hardware resource), you std::move() the object into a callee, assume it is moved and released, so you acquire a new resource, and turns out the callee did not move it and now you have two of them.
std::move tells the devs and the compiler that you _intend_ the value to be moved
sadly that isn't reflected well in it's implementation as it will "silently"
degrade even if it isn't a "move" (1)
A `std::move` which fails to compile if it can't be a move(1) it would not have this issues.
But it has other issues, mainly wrt. library design especially related to templates/generics, which probably(?) need a `std::move` which works like the current one. I think someone else in this comment section already argued that one issue with modern C++ is too much focusing on the complicated/template/const library design by experts case compared to the "day to day" usage by non experts.
(1): There is a bit of gray area in what in rust would be Copy types, for simplicity we can ignore them in this hypothetical argument about an alternative std::move design.
You can make them always on still. I've done so ever since their disappearing act started. It's not even much hidden, it's in the "Appearance" setting pane.
reply