Variadic Templates and RValue refs

1.8k views Asked by At

Consider the following C++ code

template <class... Args>
void f (const int x, const int y, Args&&... args) {
  // Do something
}

As far as I understand,Args here could either be lvalue or rvalue references, depending on the type deduction at compile time.

So, I should be able to call the function using -

float x = 40.0;
f<int, float, double>(10, 20, 30, x, 50.0);

This gives me an error saying that it could not cast x from type float to type float&&.

How do I define a function with a variadic template that accepts both lvalue and rvalue references.

2

There are 2 answers

2
Barry On BEST ANSWER

As far as I understand, Args here could either be lvalue or rvalue references, depending on the type deduction at compile time.

You're half right. Args&& would be either an lvalue or rvalue reference. But Args itself is either an lvalue reference or not a reference. A simpler case:

template <typename T> void foo(T&& ) { }

foo(1); // T is int
int x;
foo(x); // T is int&

When you specify float for x, you are specifying that that particular argument will have type float&&, and you cannot implicitly convert an lvalue float to an rvalue. You would have to cast it (via std::move):

f<int, float, double>(10, 20, 30, std::move(x), 50.0);

Or specify that it's an lvalue via float&:

f<int, float&, double>(10, 20, 30, x, 50.0);

Or simply let deduction do its thing:

f(10, 20, 30, x, 50.0);
0
Jarod42 On

If you specify argument, you have to give lvalue reference:

f<int, float&, double>(10, 20, 30, x, 50.0);

or simply let compiler deduce for you

f(10, 20, 30, x, 50.0);