Cha*_*l72 9 c++ rvalue-reference c++11
我有2个重载函数 - 一个采用L值,另一个采用R值.目的是使函数可以像:
Obj obj;
foo(obj);
Run Code Online (Sandbox Code Playgroud)
要么:
foo(Obj());
Run Code Online (Sandbox Code Playgroud)
所以,我写了2个重载函数:
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));
}
Run Code Online (Sandbox Code Playgroud)
R值过载仅需要委托给L值过载.我理解它的方式,一旦我在函数体内,任何使用v都会给我一个L值参考,除非我特意使用std::move或std::forward.因此foo(v),在R值重载内调用应该自动调用L值版本(而不是递归).
但是,编译器抱怨模棱两可:
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
Run Code Online (Sandbox Code Playgroud)
我不明白为什么这是模棱两可的.到呼叫foo()R值过载内应明确调用L值的版本.那为什么不编译呢?
简短版:尝试更新编译器.您的版本未实现http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1164.
您的第二个模板是"完美转发"模板.任何类型的函数模板参数T&&,其中T是模板参数,当参数为rvalue时,将推导出该模板参数X(其中X是参数类型),X&如果参数是左值,则推导出该模板参数.
在你的情况下,你传递了一个右值,因此T被推导出Obj(并int在你的真实代码中).如果您已经传递了变量名称或其他值为左值的东西,那么您的第二个模板将具有参数类型Obj&(T将是Obj&,并且&&应用于这样的类型保持Obj&).
但另一个模板也有这样的参数类型.因此,在重载解析期间,参数到参数的转换是相同的(完美匹配),并且需要检查另一个标准,即在部分排序规则下两个模板的特定性.如果一个模板比另一个模板更专业,那么它将由编译器选择.如果没有比另一个更专业的模板,最终的模糊性会上升.
在这种情况下,第一个模板比第二个模板更专业,因此编译器应该最终调用第一个模板.