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.
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);