C++ Logo

std-proposals

Advanced search

Re: [std-proposals] The syntax of forward and move macros

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Mon, 29 Aug 2022 10:48:06 -0400
On Mon, Aug 29, 2022 at 10:08 AM Marcin Jaczewski via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> pon., 29 sie 2022 o 15:54 Михаил Найденов via Std-Proposals <
> std-proposals_at_[hidden]> napisał(a):
> >
> > I personally think, this should be a minimal-syntax, non-overridable,
> unary postscript operator that will work for both forward and move, much
> like cast-to-T&& today
> >
> > template <typename T> Dog(T&& name) : name(name&&) {} //< forward
> > Name(string&& aName) : name(aName&&) //< move
>

There have been proposals (at least informally — maybe formally?) for the
unary `>>` operator, as in
    Dog(auto&& name) : name_(>>name) {} // in lieu of
std::forward<decltype(name)>(name)
    Name(std::string name) : name_(>>name) {} // arguably a misuse? but
would work anyway, if not artificially prohibited
Barry Revzin has been involved in this area.

The close-at-hand way to get this into C++ would be via a cast to
`decltype(name)`, which has been proposed and seen by the Committee under
the name `decltype(auto)(x)`. When `x` is a reference variable,
`decltype(x)` is the proper reference type. This would give us:
    Dog(auto&& name) : name_(decltype(auto)(name)) {}
    Name(std::string name) : name_(std::move(name)) {}
However, at last report it sounds like the Committee wasn't a big fan of
how arcane this looked.
https://lists.isocpp.org/std-proposals/2021/01/2252.php
Notice that the `decltype` is critical here; if you were to do
`auto(name)`, you'd always get a copy, because `name` is an lvalue.
    Dog(auto&& name) : name_(auto(name)) {} // valid C++23
<https://en.cppreference.com/w/cpp/language/explicit_cast>, but does not do
forwarding!!


> On Mon, Aug 29, 2022 at 2:31 AM Amar Saric via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
> >> #define ref_forward(p) (std::forward<pf::\
> >> remove_rvalue_reference<typename pf::\
> >> check_if_ref<decltype(p)>::type>>(p))
> >> #define ref_to_rvalue(p) (std::move(p))
>

Amar, you propose a "simplification" that is dozens of lines long, and ends
up delegating to `std::forward` anyway. That's... unnecessary.
std::forward is nothing more than a cast to a reference type. You can do it
like this — and my impression is that some people do, in real production
code.

    #define FWD(x) decltype(x)(x)

When `decltype(x)` is an rvalue reference type, this is a move. When
`decltype(x)` is an lvalue reference type, this is a no-op.

You don't need a macro for `std::move(x)`, as it's already pretty short.
(Certainly shorter than your `ref_to_rvalue(x)`!)

HTH,
Arthur

Received on 2022-08-29 14:48:19