我仍然不明白为什么我们需要完美转发的模板
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);
- 有关更多详细信息,请考虑 Scott Meyer's Universal References in C++11。
返回您的代码:
fwd_func(bc);
此处bc
不能作为右值引用传递,它只能作为值或左值引用传递。
要修复它,您可以创建一个单独的函数,将 big_class&
作为参数:
void fwd_func(big_class& bc){...}
或者,您可以在函数调用中专门移动 bc
:
fwd_func(std::move(bc));
或者,从 bc
:
创建一个临时副本
fwd_func(big_class(bc));
我有这个代码:(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);
- 有关更多详细信息,请考虑 Scott Meyer's Universal References in C++11。
返回您的代码:
fwd_func(bc);
此处bc
不能作为右值引用传递,它只能作为值或左值引用传递。
要修复它,您可以创建一个单独的函数,将 big_class&
作为参数:
void fwd_func(big_class& bc){...}
或者,您可以在函数调用中专门移动 bc
:
fwd_func(std::move(bc));
或者,从 bc
:
fwd_func(big_class(bc));