C++ 将R值传递给接受L值的函数时的重载模糊性

C++ 将R值传递给接受L值的函数时的重载模糊性,c++,c++11,rvalue-reference,C++,C++11,Rvalue Reference,我有两个重载函数——一个取L值,另一个取R值。其目的是使函数可以像以下那样调用: Obj obj; foo(obj); 或: 因此,我编写了两个重载函数: template <class T> void foo(T& v) { /* ... function body code goes here ... */ } template <class T> void foo(T&& v) { foo(v); } int main()

我有两个重载函数——一个取L值,另一个取R值。其目的是使函数可以像以下那样调用:

Obj obj;
foo(obj);
或:

因此,我编写了两个重载函数:

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));
}

我不明白为什么这是模棱两可的。在R值重载中调用
foo()
,应该清楚地调用L值版本。那么为什么不编译呢?

简短版本:尝试更新编译器。您的版本未实现

您的第二个模板是“完美转发”模板。当参数为右值时,类型为
T&
的任何函数模板参数,其中
T
为模板参数,将该模板参数推导出为
X
(其中
X
为参数类型),如果参数为左值,则推导出为
X&

在您的例子中,您传递了一个右值,因此
T
被推断为
Obj
(在实际代码中为
int
)。如果传递的是变量名或其他左值,则第二个模板将具有参数类型
Obj&
(T将是
Obj&
,并且
&
应用于此类类型
Obj&

但是另一个模板也有这样的参数类型。因此,在重载解析期间,参数到参数的转换是相同的(完全匹配),需要根据偏序规则检查另一个标准,即两个模板的特定性。如果一个模板比另一个模板更专业化,那么编译器将选择它。如果没有比另一个模板更专业化的模板,则会产生最终的歧义

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

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));
}
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