Search code examples
c++stringfunctionrvaluelvalue

Universal reference template type always evaluate to lvalue


My code:

#include <string>
#include <utility>
#include <iostream>

void store(std::string & val)
{
    std::cout << "lvalue " << val << '\n';
}

void store(std::string && val)
{
    std::cout << "rvalue " << val << '\n';
}

template<typename T> void print(T && val)
{
    std::cout << std::boolalpha << std::is_lvalue_reference<T>::value << " ";
    store(std::forward<T>(val));
}

int main()
{
    std::string val("something");
    print(val);
    print("something else");
}

my output:

true lvalue something
true rvalue something else

I've read on Universal referencing and understand why T is a lvalue when the input is a lvalue but I don't understand how is T a lvalue when the input is a rvalue, how does that collapse to the right paramter?


Solution

  • I don't understand how is T a lvalue when the input is a rvalue, how does that collapse to the right paramter?

    No, the input is not an rvalue.

    String literals are lvalues, and that's what you pass as a parameter to the function. That's why "true" is printed.

    Now, recall that string literals cannot be modified (String Literals).

    So, "something else" is of lenght 14 + 1 (for the null terminator), thus a const char[15].

    Now, since string literals cannot be modified, the reference will be deduced as:

     const char(&)[15];
    

    The prototype of your method is:

    store(std::string && val)
    

    which creates a temporary std::string from const char.