Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

R-value references and std::forward

40 views
Skip to first unread message

Frederick Virchanza Gotham

unread,
Dec 14, 2022, 3:44:36 AM12/14/22
to
The following code up on GodBolt:

https://godbolt.org/z/bfs3qn5Gx

prints out:

Dog takes l-value ref
Monkey takes r-value ref
Hello

I expected it to say "Monkey takes l-value ref".

Is the behaviour undefined because of my use of 'forward' on Line #22? Should 'forward' only be used with a so-called 'template parameter forwarding reference'?

Bo Persson

unread,
Dec 14, 2022, 4:27:06 AM12/14/22
to
You are using it wrong, anyway. When the value is an int&, you should
"forward" is using forward<int&>(arg).

That's what happens with a forwarding reference.



Frederick Virchanza Gotham

unread,
Dec 14, 2022, 4:48:20 AM12/14/22
to
On Wednesday, December 14, 2022 at 9:27:06 AM UTC, Bo Persson wrote:

> You are using it wrong, anyway. When the value is an int&, you should
> "forward" is using forward<int&>(arg).
>
> That's what happens with a forwarding reference.


If I knew for certain that it was an "int&" then why would I bother using 'forward' on it?

The question I'm asking is why 'forward' in this case is turning an L-value into an R-value?
Is it because it's UB to use 'forward' on something that isn't a "template parameter forwarding reference"?

Bo Persson

unread,
Dec 14, 2022, 6:43:06 AM12/14/22
to
On 2022-12-14 at 10:48, Frederick Virchanza Gotham wrote:
> On Wednesday, December 14, 2022 at 9:27:06 AM UTC, Bo Persson wrote:
>
>> You are using it wrong, anyway. When the value is an int&, you should
>> "forward" is using forward<int&>(arg).
>>
>> That's what happens with a forwarding reference.
>
>
> If I knew for certain that it was an "int&" then why would I bother using 'forward' on it?

Beats me, it was your example.

>
> The question I'm asking is why 'forward' in this case is turning an L-value into an R-value?

Because that's how template argument deduction works. When you
explicitly supply <int> to a function returning T&&, you get an int&&.
No surprise here.

> Is it because it's UB to use 'forward' on something that isn't a "template parameter forwarding reference"?

No, but not very useful. The whole idea of std::forward is that it can
adapt to the deduced template parameter. If there is no template, it is
outside if the intended use pattern.

Juha Nieminen

unread,
Dec 14, 2022, 7:42:12 AM12/14/22
to
Frederick Virchanza Gotham <cauldwel...@gmail.com> wrote:
> If I knew for certain that it was an "int&" then why would I bother
> using 'forward' on it?

std::forward is useful mainly with templated types. It's not all that
useful with concrete types.

The main idea with std::forward is that it preserves lvalues as lvalues
and rvalues as rvalues when passing parameters to other functions (if
you don't use std::forward and tried to pass the function parameter
directly then an rvalue would decay to an lvalue, because a named
variable always decays to an lvalue, unless explicitly cast to an
rvalue). In order to do this you need to provide it with the original
type of the value you are passing, as a template parameter. This
would usually be the original template type that that parameter has.

Frederick Virchanza Gotham

unread,
Dec 14, 2022, 9:46:59 AM12/14/22
to
On Wednesday, December 14, 2022 at 11:43:06 AM UTC, Bo Persson wrote:

> Because that's how template argument deduction works. When you
> explicitly supply <int> to a function returning T&&, you get an int&&.
> No surprise here.


It all makes sense after learning about the "reference collapsing" rules.

Although to be honest it does surprise me that those reference collapsing rules made it into the Standard.

Öö Tiib

unread,
Dec 15, 2022, 8:49:06 AM12/15/22
to
That is empty critique as it lacks constructive explanation what rules
and/or wording you would expect to be better.

Bonita Montero

unread,
Dec 15, 2022, 10:39:08 AM12/15/22
to
std::forward is for templated forwarding-references, not references you
know that they're r-value-references. With that you can use move() to
have a somewhat clearer code. And moving ints looks strange to me.

Bonita Montero

unread,
Dec 15, 2022, 1:03:35 PM12/15/22
to
Am 14.12.2022 um 13:41 schrieb Juha Nieminen:

> The main idea with std::forward is that it preserves lvalues as lvalues
> and rvalues as rvalues when passing parameters to other functions ...

And it preserves const-ness, even with r-value references.


Andrey Tarasevich

unread,
Dec 17, 2022, 1:56:00 PM12/17/22
to
On 12/14/2022 12:44 AM, Frederick Virchanza Gotham wrote:
> Is the behaviour undefined because of my use of 'forward' on Line #22?

No. Why would it be? The behavior of `std::forward<>` is well-specified.
Regardless of how and where you use it, it will simply behave in
accordance with its specification.

> Should 'forward' only be used with a so-called 'template parameter forwarding reference'?

Yes, it probably should. That's what it's for.

--
Best regards,
Andrey
0 new messages