我仍然不明白为什么我们需要完美转发的模板

I still can't get my head around why we need the template for perfect fwd

我有这个代码:(live eg: https://godbolt.org/z/js1qK9hd1

struct big_class
{
    std::string s1;
    std::string s2;
    std::string s3;
    std::string s4;
    std::string s5;
    std::string s6;
    std::string s7;
};

void func(const big_class &bc)
{
    std::cout << bc.s1 << bc.s2 << bc.s3 << bc.s4 << bc.s5 << bc.s6 << bc.s7 << std::endl;
}

void fwd_func(big_class &&bc)
{
    func(std::forward<big_class>(bc));
}

template<typename T>
void prefect_fwd_func(T &&bc)
{
    func(std::forward<T>(bc));
}

int main()
{
    big_class bc{"1", "2", "3", "4", "5", "6", "7"};

    std::cout << "func" << std::endl;
    func(bc);
    std::cout << "fwd_func" << std::endl;
    fwd_func(bc);
    std::cout << "perfect_fwd_func" << std::endl;
    prefect_fwd_func(bc);
}

所以这里 fwd_func 不起作用 - 但在我看来它与模板 perfect_fwd_func 基本相同 - 只是它不是模板。

为什么这个有效? - 它说它不能将 lval 绑定到 rval。我认为它与模板 T && 衰减成 T 之类的东西有关,但仍然不能完全混淆它......两者之间有什么区别?

如果我只想传递一个 big_class 类型 - 那么我假设我最好的选择是通过 const 引用传递它...

不同于big_class&&,它是一个右值引用,只能接受一个右值引用,模板版本T&&是一个通用引用/转发引用.

当您将某些内容传入模板函数时,T&& 可能会被推断为右值引用 (big_class&&) 或左值引用 (big_class&)。

所以它可以为一个类型生成 2 个不同的函数 U:

void prefect_fwd_func<U>(U&& bc);

void prefect_fwd_func<U&>(U& bc);

返回您的代码:

fwd_func(bc);

此处bc不能作为右值引用传递,它只能作为值或左值引用传递。

要修复它,您可以创建一个单独的函数,将 big_class& 作为参数:

void fwd_func(big_class& bc){...}

或者,您可以在函数调用中专门移动 bc

fwd_func(std::move(bc));

或者,从 bc:

创建一个临时副本
fwd_func(big_class(bc));