为什么或何时应该在调用前将可调用函数参数转换为右值?
Why or when should I cast callable function parameters to an rvalue before invocation?
到目前为止,我考虑过传递和调用一个可调用对象
template <class Fct, class... Args> void f(Fct&& g, Args&&... args)
{
g(std::forward<Args>(args)...);
}
是必经之路。现在在 this talk (at 34 min.) and in the std::invoke 示例实现中,我看到了上面代码片段的等价物,它在调用它之前有条件地将可调用对象转换为右值引用,
template <class Fct, class... Args> void f(Fct&& g, Args&&... args)
{
std::forward<Fct>(g)(std::forward<Args>(args)...);
}
我假设这个修改只影响闭包,但我仍然不明白为什么第二个版本更可取:强制转换只影响右值参数,调用时不应复制任何状态,对吗?我还检查了 std::function::operator() 是否在 &
和 &&
上过载,以通过替代上述代码段的库获得提示,但事实并非如此。
提前感谢您的提示和回答!
完美转发的重点是尽可能的保留原始信息
g(std::forward<Args>(args)...);
会丢弃原函数对象的rvalue/lvalue信息,g
会总是被当作左值。
这会产生明显的效果,例如:
struct foo {
void operator()(int) & {
std::cout << "& called\n";
}
void operator()(int) && {
std::cout << "&& called\n";
}
};
foo{}(1)
将调用第二个 operator()
。如果您在没有 std::forward
的情况下使用第一种方法,f(foo{}, 1)
将调用第一个 operator()
.
到目前为止,我考虑过传递和调用一个可调用对象
template <class Fct, class... Args> void f(Fct&& g, Args&&... args)
{
g(std::forward<Args>(args)...);
}
是必经之路。现在在 this talk (at 34 min.) and in the std::invoke 示例实现中,我看到了上面代码片段的等价物,它在调用它之前有条件地将可调用对象转换为右值引用,
template <class Fct, class... Args> void f(Fct&& g, Args&&... args)
{
std::forward<Fct>(g)(std::forward<Args>(args)...);
}
我假设这个修改只影响闭包,但我仍然不明白为什么第二个版本更可取:强制转换只影响右值参数,调用时不应复制任何状态,对吗?我还检查了 std::function::operator() 是否在 &
和 &&
上过载,以通过替代上述代码段的库获得提示,但事实并非如此。
提前感谢您的提示和回答!
完美转发的重点是尽可能的保留原始信息
g(std::forward<Args>(args)...);
会丢弃原函数对象的rvalue/lvalue信息,g
会总是被当作左值。
这会产生明显的效果,例如:
struct foo {
void operator()(int) & {
std::cout << "& called\n";
}
void operator()(int) && {
std::cout << "&& called\n";
}
};
foo{}(1)
将调用第二个 operator()
。如果您在没有 std::forward
的情况下使用第一种方法,f(foo{}, 1)
将调用第一个 operator()
.