Search code examples
c++c++17perfect-forwardingforwarding-reference

Universal reference in variadic template class is treated as rvalue reference


I am trying to create variadic template that can get lvalues, rvalues and rvalue references as arguments. But it seems that T&& is treated as rvalue reference and wouldn't accept other types.

Am I missing something? I thought that && is universal reference when used in templates.

#include <string>

template <typename... T>
struct MyClass
{
    MyClass(T&&... values)
    {
    }
};

int main()
{
    std::string string_value;
    
    //MyClass my_class(string_value); // class template argument deduction failed
    
    //MyClass<std::string> my_class(string_value); // cannot bind rvalue reference of type
    
    MyClass<std::string> my_class(std::move(string_value)); // OK
    
    return 0;
}

https://coliru.stacked-crooked.com/a/7996ea4ab81e9b5d


Solution

  • That's not a universal/forwarding reference.

    From cppreference:

    An rvalue reference to a cv-unqualified template parameter is not a forwarding reference if that parameter is a class template parameter:

    template<class T>
    struct A
    {
        template<class U>
        A(T&&, U&&, int*); // #1: T&& is not a forwarding reference
                           //     U&& is a forwarding reference
     
        A(T&&, int*);      // #2: T&& is not a forwarding reference
    };
    ```i