Search code examples
c++c++11variadic-templateslvaluervalue

Variadic Templates and RValue refs


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.


Solution

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