> I suppose you propose to automatically forward the variable at the last use and not before?
No, it would always forward. Remember: forwarding doesn't do anything
in and of itself. What does something is how the recipient of the
forwarding process uses it.
But forwarding moves from your variable in half the cases, so that's not quite correct? 

But the meaning of a piece of syntax
should not change based on where it is in a function or what follows

Why not, if this does what you want in most cases? At least correct behavior is guaranteed, and it's an easy to understand, observable mechanism. 
Signature of functions can be hard to track down, if my rvalue-ref is moved automatically on the first rvalue/forwarding-ref signature it means that we now have to lvalue-ref-cast every use before the last or else an unfortunate overload can silently break the code. A special operation on last use is actually a more observable process. 

This is also why we shouldn't allow implicit moves on the last use of
a local variable in a function, even if a move operation was available
to that usage. `return name` is OK to move from because that statement
will *always* be the last thing executed in the function no matter
where it appears relative to other code. But moving code around
shouldn't affect the behavior in terms of overload resolution and the

The bigger problem with implicit moves is that it effectively changes your program in ways that are hard to predict.  If your object destructor has side-effects and your code depends on it being called at the end of X function scope, that's a bug (still going to be called, but with another state). 
This kind of type is fairly rare though and i would be ok with opt-in implicit moves. "Pass the data in the most efficient way for the last use if an overload is found" is a simple enough rule - and i think code that performs semantically differently depending on reference qualifiers isn't the kind of code to base language design decisions on. Furthermore you still could get manual control by performing decay-copy etc, but that would be "typing more to do the special case" instead of "typing more to do the obvious thing". 

Le dim. 17 janv. 2021 à 18:31, Drew Gross via Std-Proposals <std-proposals@lists.isocpp.org> a écrit :
The logger implementation we have is "deferred". When you call LogValue, it saves data to an in-memory data structure, and that data structure saves to disk later on. It means the expensive part is deferred until after all the important work is done, and can be optimized via batching some operations. It also means that the LogValue function can itself be optimized by moving from it's argument into the in-memory data structure, instead of copying, when provided with an rvalue.

On Sun, Jan 17, 2021 at 9:21 AM Jason McKesson via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
On Sun, Jan 17, 2021 at 4:27 AM Drew Gross via Std-Proposals
<std-proposals@lists.isocpp.org> wrote:
> Some examples of when you don't want to forward a forwarding reference, might be easy to create bugs if it forwarded automatically:
> 1) A generic logging wrapper function
> ```
> auto LoggedCall(auto >&& f, auto >&& v) {
>     LogValue(v);
>     return f(v); // Oops, v was moved from! (Maybe, depending on signature of LogValue)
> }
> ```

Why would a logging function move from its parameter? It should take
it as a `const&`.

> 2) A generic concatenate function
> ```
> auto Concatenate(auto >&& c1, auto >&& c2) {
>     std::vector<decltype(c1)::value_type> result;
>     using std::size;
>     result.reserve(size(c1) + size(c2)); // Oops! c1 and c2 were moved from (OK only if size's signature is weird for c1/c2's type, but you get the point)
>     // ... add c1 and c2 to result ...
>     return result;
> }
> ```

Again, why would `size` move from its parameter?
Std-Proposals mailing list
Std-Proposals mailing list