Function template overloading on r-value and l-value references

71 Views Asked by At

In c++ primer about "reference collapsing" "overloading function template on r-values and l-values" it is said:

template <typename T> void f(T&&); // binds to nonconst rvalues
template <typename T> void f(const T&); // lvalues and const rvalues

"As with nontemplate functions, the first version will bind to modifiable rvalues and the second to lvalues or to const rvalues."

The example is from the book but what I think is a bit different:

The first version will bind to modifiable r-values and modifiable l-values:

template <typename T>
void foo(T&& x)
{
    cout << "foo(T &&)\n";
}

template <typename T>
void foo(T const& x)
{
    cout << "foo(T const&)\n";
}


int main()
{

    int i = 21;
    int const ic = i;
    foo(5); // foo(int&&)
    foo(i); // foo(int&& ) -> new instantiation foo(int& x) --- here
    foo(ic); // foo(int const&)
    foo(std::move(i)); // foo(int&&)
    foo(std::move(ic));// foo(&&) -> foo(int const&&)


    cout << "\ndone!\n";
}

As you can see when I pass i which is a modifiable l-value then foo(int&&) is called not foo(int const&) that is the compiler will apply reference collapsing yielding in instantiating a version of foo this way:

 void foo(int& x){}; // after reference collapsing

So the version taking a reference to const l-value is preferred only if the argument is a constant l-value or const r-value. (overload resolution and function matching)

That is what I think. What do you think? Thank you!

0

There are 0 best solutions below