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

陌路散爱 提交于 2019-12-04 11:58:38

问题


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:


Short version: Try updating your compiler. Your version doesn't implement http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1164 .

Your second template is a "perfect forwarding" template. Any function template parameter of type T&&, where T is a template parameter will deduce that template parameter to X (where X is the argument type) when the argument is an rvalue, and to X& if the argument is an lvalue.

In your case you passed an rvalue, so T was deduced to Obj (and int in your real code). If you would have passed a variable name or something else that is an lvalue, your second template would have the parameter type Obj& (T would be Obj&, and && applied to such a type stays Obj&).

But the other template also has such a parameter type. So during overload resolution the conversion of the argument to the parameter is the same (perfect match), and another criteria needs to inspected, the specifity of the two templates, under the partial ordering rule. If one template is more specialized than the other template, then it will be chosen by the compiler. If there is no template more specialized than the other one, a final ambiguity is risen.

In this case, the first template is more specialized than the second template, and hence the compiler should call the first template finally.



来源:https://stackoverflow.com/questions/11623142/overload-ambiguity-when-passing-r-value-to-function-that-takes-l-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!