In the code below, why should I use std::forward
when passing around arguments?
在下面的代码中,为什么我在传递参数时使用std :: forward?
class Test {
public:
Test() {
std::cout << "ctor" << std::endl;
}
Test(const Test&) {
std::cout << "copy ctor" << std::endl;
}
Test(const Test&&) {
std::cout << "move ctor" << std::endl;
}
};
template<typename Arg>
void pass(Arg&& arg) {
// use arg..
return;
}
template<typename Arg, typename ...Args>
void pass(Arg&& arg, Args&&... args)
{
// use arg...
return pass(args...); // why should I use std::forward<Arg>(args)... ?
}
int main(int argc, char** argv)
{
pass(std::move<Test>(Test()));
return 0;
}
The code with or without std::forward
doesn't show any copy/move around.
带或不带std :: forward的代码不显示任何复制/移动。
1 个解决方案
#1
6
There are a number of good posts on what std::forward
does and how it works (such as here and here).
关于std :: forward做什么以及如何工作(例如这里和这里)有很多好的帖子。
In a nutshell, it preserves the value category of its argument. Perfect forwarding is there to ensure that the argument provided to a function is forwarded to another function (or used within the function) with the same value category (basically r-value vs. l-value) as originally provided. It is typically used with template functions where reference collapsing may have taken place (involving universal/forwarding references).
简而言之,它保留了其参数的值类别。完美转发是为了确保提供给函数的参数被转发到另一个函数(或在函数内使用),其具有与最初提供的相同的值类别(基本上是r值与l值)。它通常与模板函数一起使用,其中可能发生了引用折叠(涉及通用/转发引用)。
Consider the code sample below. Removing the std::forward
would print out requires lvalue
and adding the std::forward
prints out requires rvalue
. The func
is overloaded based on whether it is an rvalue or an lvalue. Calling it without the std::forward
calls the incorrect overload. The std::forward
is required in this case as pass
is called with an rvalue.
考虑下面的代码示例。删除std :: forward将打印输出需要左值并添加std :: forward打印输出需要rvalue。根据fval是rvalue还是左值,func会被重载。在没有std :: forward的情况下调用它会调用不正确的重载。在这种情况下需要std :: forward,因为使用rvalue调用pass。
#include <utility>
#include <iostream>
class Test {
public:
Test() {
std::cout << "ctor" << std::endl;
}
Test(const Test&) {
std::cout << "copy ctor" << std::endl;
}
Test(Test&&) {
std::cout << "move ctor" << std::endl;
}
};
void func(Test const&)
{
std::cout << "requires lvalue" << std::endl;
}
void func(Test&&)
{
std::cout << "requires rvalue" << std::endl;
}
template<typename Arg>
void pass(Arg&& arg) {
// use arg here
func(std::forward<Arg>(arg));
return;
}
template<typename Arg, typename ...Args>
void pass(Arg&& arg, Args&&... args)
{
// use arg here
return pass(std::forward<Args>(args)...);
}
int main(int, char**)
{
pass(std::move<Test>(Test()));
return 0;
}
#1
6
There are a number of good posts on what std::forward
does and how it works (such as here and here).
关于std :: forward做什么以及如何工作(例如这里和这里)有很多好的帖子。
In a nutshell, it preserves the value category of its argument. Perfect forwarding is there to ensure that the argument provided to a function is forwarded to another function (or used within the function) with the same value category (basically r-value vs. l-value) as originally provided. It is typically used with template functions where reference collapsing may have taken place (involving universal/forwarding references).
简而言之,它保留了其参数的值类别。完美转发是为了确保提供给函数的参数被转发到另一个函数(或在函数内使用),其具有与最初提供的相同的值类别(基本上是r值与l值)。它通常与模板函数一起使用,其中可能发生了引用折叠(涉及通用/转发引用)。
Consider the code sample below. Removing the std::forward
would print out requires lvalue
and adding the std::forward
prints out requires rvalue
. The func
is overloaded based on whether it is an rvalue or an lvalue. Calling it without the std::forward
calls the incorrect overload. The std::forward
is required in this case as pass
is called with an rvalue.
考虑下面的代码示例。删除std :: forward将打印输出需要左值并添加std :: forward打印输出需要rvalue。根据fval是rvalue还是左值,func会被重载。在没有std :: forward的情况下调用它会调用不正确的重载。在这种情况下需要std :: forward,因为使用rvalue调用pass。
#include <utility>
#include <iostream>
class Test {
public:
Test() {
std::cout << "ctor" << std::endl;
}
Test(const Test&) {
std::cout << "copy ctor" << std::endl;
}
Test(Test&&) {
std::cout << "move ctor" << std::endl;
}
};
void func(Test const&)
{
std::cout << "requires lvalue" << std::endl;
}
void func(Test&&)
{
std::cout << "requires rvalue" << std::endl;
}
template<typename Arg>
void pass(Arg&& arg) {
// use arg here
func(std::forward<Arg>(arg));
return;
}
template<typename Arg, typename ...Args>
void pass(Arg&& arg, Args&&... args)
{
// use arg here
return pass(std::forward<Args>(args)...);
}
int main(int, char**)
{
pass(std::move<Test>(Test()));
return 0;
}