Std::forward 和模板类型推导

Std::forward and template type deduction

我编写了以下小程序来了解 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&&) 。关于 std::forward 的工作原理,我是完全理解错误还是存在细微错误?或者更糟的是,代码是否应该按照我的预期工作,也许我搞砸了我的编译器实现? Btw.I正在使用 g++ 7.2

Did I understand something completely wrong about how std::forward works

是的。 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 强制转换为右值引用,而不是像您这样的左值引用预期。