C++中的转发参数

Forwarding params in C++

我有一些 class 和包装纸。例如:

#include <iostream>
#include <string>

template<typename T>
class inner
{
public:
    void f(T& v) { std::cout<<"lvalue: "<<v<<std::endl;}
    void f(T&& v) { std::cout<<"rvalue: "<<v<<std::endl;}
};

template<typename T>
class wrapper
{
public:
    template<typename _T>
    void f(_T&& v) { i.f(std::forward<T>(v)); } //(1)

private:
    inner<T> i;
};

int main()
{
    wrapper<std::string> c;
    //inner<std::string> c;

    c.f("r");

    std::string s = "l";
    c.f(s);
}

cinner的情况下输出正确:

rvalue: r
lvalue: l

但是当cwrapper时输出不正确:

rvalue: r
rvalue: l

为什么左值变成右值?

如果 wrapperf(1) 定义有什么区别:

    template<typename _T>
    void f(_T v) { i.f(std::forward<T>(v)); } //without &&

因为你在做:

template<typename _T>
void f(_T&& v) { i.f(std::forward<T>(v)); } //(1)
                                  ^
                                  T, not _T

您总是只使用 T,而不是 v 推导 类型。为了更加清楚,您实际上是在做:

template <typename _T>
void f(_T&& v) {
    i.f(std::forward<std::string>(v));
}

std::forward<std::string>(v)的类型是string&&

第二个问题:

template<typename _T>
void f(_T v) { i.f(std::forward<T>(v)); } //without &&

由于 _T 永远不会在此处推断为引用类型,因此 std::forward<T>(v) 将等同于 std::move(v) - 它只是对右值引用的强制转换。