Overload ambiguity when passing R-value to function that takes L-value

Viewed 1414

I have 2 overloaded functions - one takes an L-value, and the other takes an R-value. The purpose is so that the function can be called like:

Obj obj;
foo(obj);

OR:

foo(Obj());

So, I write 2 overloaded functions:

template <class T>
void foo(T& v)
{
  /* ... function body code goes here ... */
}

template <class T>
void foo(T&& v)
{
    foo(v);
}

int main()
{
    foo(int(5));
}

The R-value overload merely needs to delegate to the L-value overload. The way I understand it, once I'm in the body of the function, any use of v gives me an L-value reference, unless I specifically use std::move or std::forward. So calling foo(v) within the R-value overload should automatically call the L-value version (rather than recursing.)

But, the compiler complains about ambiguity:

test.cpp: In function ‘void foo(T&&) [with T = int]’:
test.cpp:305:12:   instantiated from here
test.cpp:299:2: error: call of overloaded ‘foo(int&)’ is ambiguous

I don't understand why this is ambiguous. The call to foo() within the R-value overload should clearly call the L-value version. So why doesn't this compile?

1 Answers
Related