3

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.

Barry
  • 286,269
  • 29
  • 621
  • 977
ssb
  • 7,422
  • 10
  • 36
  • 61

2 Answers2

4

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);
Jarod42
  • 203,559
  • 14
  • 181
  • 302
4

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);
igel
  • 358
  • 1
  • 8
Barry
  • 286,269
  • 29
  • 621
  • 977
  • The simple deduction gives an error saying... `.....file.h:41:87: note: cannot convert ‘x’ (type ‘float’) to type ‘float&&’`. I fixed the typo with the template... – ssb Jun 24 '15 at 18:44
  • @subzero Not with exactly the function in your question, it won't. – Barry Jun 24 '15 at 18:58