If the issue with >> is that it complicates template parsing, why can't we just require it to be parenthesized? That is, FWD(x) would be written as (>> x), and because the >> follows an opening parenthesis, it is easy to tell that it cannot be two closing angle brackets. This is ugly, especially considering that it would be rare for the argument to be a compound expression, but I think it's still better than not having this feature at all. We already have precedent in the standard: fold-expressions are required to be parenthesized; this confuses some people at first, but overall fold-expressions are a huge success.



On Fri, Jan 15, 2021 at 11:01 AM Arthur O'Dwyer via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
On Fri, Jan 15, 2021 at 10:44 AM Bengt Gustafsson via Std-Proposals <std-proposals@lists.isocpp.org> wrote:

I think it should be a prefix operator, [...]

Yes, >>x has been proposed before, but shot down.

The OP's specific idea of postfix `&` or `&&` doesn't work because
    return x&&-y;
    return x&-y;
 already parse as meaningful expressions in C++.

Anyway, with OP's specific idea for syntax gone, all that remains is OP's specific idea for semantics. OP should think about what this hypothetical facility would do with a variable `x` whose decltype is a non-reference type, e.g.
    auto foo(auto x) { return bar(HYPOTHETICAL_FWD_SYNTAX(x)); }  // Moves (like std::forward/static_cast<decltype(x)>)? Copies? Ill-formed?

Bengt wrote:
Preferably the operator should work both as move and as forward, it is a
struggle understanding which one to use

Move and forward are different operations, though.

    auto move_from(auto&& x) { return std::move(x); }
    auto forward_from(auto&& x) { return std::forward<decltype(x)>(x); }
    int main() {
        std::shared_ptr<int> o = std::make_shared<int>(42);
        auto x = forward_from(o);  // copies
        auto y = move_from(o);  // moves
        assert(o == nullptr && x != nullptr && y != nullptr && x == y);
    }

But my understanding is that you can always use forward<T>(x) and
move(x) is just a shortcut which is allowed when you know that x is a
parameter passed by rvalue reference.

No!  `move` unconditionally moves; `forward<T>` is conditional, either moving or not-moving, based on the value of T (which is why it has to take a template parameter like that).
Unfortunately I haven't written a blog post on this topic yet. But now it's on my list.

HTH,
–Arthur
--
Std-Proposals mailing list
Std-Proposals@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals


--
Brian Bi