Question

I am trying to understand how lvalues bind to rvalue references. Consider this code:

#include <iostream>

template<typename T>
void f(T&& x) {
    std::cout << x;
}

void g(int&& x) {
    std::cout << x;
}

int main() {
    int x = 4;
    f(x);
    g(x);
    return 0;
}

While the call to f() is fine, the call to g() gives a compile-time error. Does this kind of binding work only for templates? Why? Can we somehow do it without templates?

Was it helpful?

Solution

Since T is a template argument, T&& becomes a forwarding-reference. Due to reference collapsing rules, f(T& &&) becomes f(T&) for lvalues and f(T &&) becomes f(T&&) for rvalues.

OTHER TIPS

0x499602D2 has already answered your question; nevertheless, the following changes to your code might give further insights.

I have added a static_assert to f to check the deduced type:

#include <type_traits>

template<typename T>
void f(T&& x) {
    static_assert(std::is_same<T&&, int&>::value,"");
    std::cout << x;
}

The assert does not fail, so the type of x in f is eventually int& (in this particular example).

I have changed how g is called in main:

g(std::move(x));

Now the code compiles and the program works as expected and prints 44.

Hope this helps a bit in understanding rvalue references.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top