With rvalue references, many redundant copies may be elided, but that seems to require me to write the same function multiple times (one for an rvalue reference, one for a const
lvalue reference). But the standard library seems to only need to declare some functions once.
For example:
#include <iostream>
#include <tuple>
void foo(int&& x){
x = 2;
}
int main()
{
int x = 1;
foo(x); // compile error
std::make_tuple(x); // ok
std::cout << x << std::endl;
}
Calling foo(x)
is a compile error, because I cannot convert implicitly from int
to int&&
. But I am perplexed as to why std::make_tuple
would work. The reference says that it only accepts rvalue reference parameters. It also seems to not make copies when the value passed into it is an ravlue reference, but it would make a copy (as most would expect) when used as in my sample above.
How can I make foo
work like this?
The reference says that it only accepts rvalue reference parameters.
No, this is forwarding reference, which could serve as both lvalue reference and rvalue reference, according to the value category of the passed-in argument.
How can I make
foo
work like this?
The point of declaring a forwarding reference is (1) type deduction is necessary, that means you need to make foo
a function template here; (2) the parameter x
has the exact form of T&&
for the template parameter T
. e.g.
template <typename T>
void foo(T&& x){
x = 2;
}
then
int x = 1;
foo(x); // lvalue passed, T is deduced as int&, parameter's type is int&
foo(1); // rvalue passed, T is deduced as int, parameter's type is int&&
Note this is true for std::make_tuple
too, even it's using template parameter pack. And better to bear in mind that even forwarding reference looks like rvalue reference but they're different things.
BTW: std::forward is usually used with forwarding reference to preserve the value category of the argument e.g. when forwarding it to other functions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With