Std :: forward和模板类型推导

时间:2017-11-25 17:36:58

标签: c++ forward forwarding-reference

我编写了以下小程序来了解std :: forward的工作原理。

#include <iostream>
#include <memory>

template<class T>
void foo3(T&& bar){
    std::cout<<"foo3&&"<<std::endl;
}

template<class T>
void foo3(T& bar){
    std::cout<<"foo3&"<<std::endl;
}

template<class T>
void foo(T&& bar){
    std::cout<<"foo&&"<<std::endl;
    foo3(std::forward<T>(bar));
}

template<class T>
void foo(T& bar){
    std::cout<<"foo&"<<std::endl;
    foo3(std::forward<T>(bar));
}

int main(int argc, char * argv []){
    int i = 1;
    foo(2);
    foo(i);
    return 0;
}

我希望得到以下结果:

"foo&&"
"foo3&&"
"foo&"
"foo3&"

但是,我得到以下结果,我无法解释:

"foo&&"
"foo3&&"
"foo&"
"foo3&&"

因此,如果用左值调用foo,我希望foo将转发左值并调用foo3的左值版本。然而,一直调用foo3(T&amp;&amp;)。我是否理解std :: forward如何工作还是存在一个微妙的错误?或者更糟糕的是,代码是否应该像我预期的那样工作,也许我搞砸了我的编译器实现? 顺便说一下,我正在使用g ++ 7.2

1 个答案:

答案 0 :(得分:4)

  

我是否理解std :: forward如何工作完全错误

是。 std::forward用于转发引用,而bar中的void foo(T&)则不是。如果你不尊重这一点,你会得到一些奇怪的行为。

要理解为什么你需要了解std::forward实际上做了什么。这只是演员

static_cast<T&&>(t)

tstd::forward的参数。因此,foo的最终调用如下所示:

std::cout<<"foo&"<<std::endl;
foo3(std::forward<int>(bar));

T被推导为int,如果查看演员表,您会看到它将bar转换为右值引用,而不是像您预期的左值引用。