使用rvalue/lvalue了解模板参数推导

hiv*_*ert 8 c++ templates rvalue lvalue c++11

这是函数模板的后续跟不识别左值

让我们玩下面的代码:

#include <iostream>
template <class T>
void func(T&&) {
  std::cout<<"in rvalue\n";
}

template <class T>
void func(const T&) {
  std::cout<<"in lvalue\n";
}

int main()
{
    double n=3;
    func<double>(n);
    func(n);
}
Run Code Online (Sandbox Code Playgroud)

它打印:

in lvalue
in rvalue
Run Code Online (Sandbox Code Playgroud)

我不明白第二次电话会发生什么.编译器如何解析模板参数?为什么没有歧义?

Ker*_* SB 13

当你说func<double>(n),没有参数推论,因为你指定了参数,所以选择是在func(double &&)和之间func(const double &).前者不可行,因为右值引用不能绑定到左值(即n).

func(n)执行参数推断.这是一个复杂的主题,但简而言之,您有两个可能的候选人:

T = double &:    func(T &&)       -->   func(double &)          (first overload)
T = double:      func(const T &)  -->   func(const double &)    (second overload)
Run Code Online (Sandbox Code Playgroud)

第一过载是严格更好,因为它需要(即从参数值中的一个较少转换doubleconst double).

神奇的成分是"参考折叠",这意味着T &&T它本身就是一个引用类型时可以是左值引用(具体地,double & &&变为double &,并且允许第一个推论存在).

  • @piwi除了引入rvalue引用之外,它已经过时了.@Kerrek并没有真正说清楚:当模板参数推断发生时,`func(T &&`)中的`&&`是**不是一个右值引用,而是一个通用引用,可以成为右值引用(如果参数是右值)或左值引用(如果参数是左值).Scott Meyer在http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers中解释了这一点.这是我为这个特定问题推荐的文章. (3认同)