当将R值传递给需要L值的函数时,过载模糊性 [英] Overload ambiguity when passing R-value to function that takes L-value

查看:136
本文介绍了当将R值传递给需要L值的函数时,过载模糊性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有2个重载函数 - 一个采用L值,另一个采用R值。目的是使函数可以像下面这样调用:

  Obj obj; 
foo(obj);

或:

  foo(Obj());因此,我写了两个重载的函数:


template< class T>
void foo(T& v)
{
/ * ...函数体代码放在这里... * /
}

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

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

R值过载仅需要委托给L值重载。我的理解方式,一旦我在函数的身体,任何使用 v 给我一个L值引用,除非我特别使用 std :: move std :: forward 。因此,在R值重载过程中调用 foo(v)应该会自动调用L值版本(而不是递归)。



但是,编译器会抱怨模糊性:

  test.cpp:在函数'void foo(T& )[with T = int]':
test.cpp:305:12:从这里实例化
test.cpp:299:2:错误:调用重载的'foo(int&

我不明白为什么这是不明确的。在R值重载期间对 foo()的调用应清楚地调用L值版本。那么为什么不编译呢?

解决方案

您的版本未实施 http://www.open -std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1164



您的第二个范本是「完美转寄」范本。 T&& ,其中 T 是模板参数的任何函数模板参数将会将模板参数推导为 X (其中 X 是参数类型),当参数是右值时, X& ; 如果参数是一个左值。



在您的情况下,您传递了一个右值,因此 T 被推导为 Obj (和 int )。如果你传递了一个变量名或者其他的值为左值,你的第二个模板将会有参数类型 Obj& (T会是 Obj& ; &&& 应用于此类型保留 Obj& )。



但是其他模板也有这样的参数类型。因此,在重载解析期间,参数到参数的转换是相同的(完全匹配),另一个标准需要检查,两个模板的 specifity em>规则。如果一个模板比另一个模板更专业,那么它将由编译器选择。如果没有比另一个模板更专业的模板,最终的模糊性上升。



在这种情况下,第一个模板比第二个模板更专业,因此编译器应该最终调用第一个模板。 p>

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?

解决方案

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.

这篇关于当将R值传递给需要L值的函数时,过载模糊性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆