我正在查看 std::function
实现及其调用 operator()
template<typename Ret, typename... ArgTypes>
Ret function< Ret (ArgTypes...)>::operator()(ArgTypes...args) const
{
// some stuff
return invoker(functor, std::forward<ArgTypes>(args)...);
}
我特别想知道,为什么它使用 std::forward
这里?这与完美转发有什么关系吗?
因为只有operator()
才能完美转发是一个带有可变模板声明的模板 template<typename... Args>
(事实并非如此,声明是 std::function 的部分特化)。
在这里使用 std::forward 的目的是什么?我很困惑:-)?
最佳答案
您是对的,这不是典型的“完美转发”场景。一个简短的例子可以帮助说明动机。假设类型 A
带有检测构造函数和析构函数:
#include "A.h"
#include <functional>
#include <iostream>
int
main()
{
A a1{1};
A a2{2};
std::function<void(A, A&)> f{[](A x, A& y){}};
f(a1, a2);
}
这将输出:
A(int state): 1
A(int state): 2
A(A const& a): 1
A(A&& a): 1
~A(1)
~A(-1)
~A(2)
~A(1)
解释:
a1
和 a2
在堆栈上构建。然后传入时传入function
调用者,a1
首先复制绑定(bind)到第一个按值参数,然后是std::forward<A>
被称为 a1
这将它从按值参数转移到 lambda 中。
相比之下,a2
无需复制即可绑定(bind)到 function
A&
参数,然后是 std::forward<A&>(a2)
被调用,转发a2
作为左值而不是右值,这绑定(bind)到 A&
lambda 的参数。
然后事情就被破坏了。 ~A(-1)
表示一个 A
的破坏处于移动构建状态,使用此工具 A
.
总而言之,即使ArgTypes
不像通常的完美转发习语那样推导出来,我们仍然希望按值转发 ArgTypes
作为右值,并通过引用 ArgTypes
作为左值。所以std::forward
恰好完全符合我们的要求。
关于c++ - std::function operator() 和 std::forward 发生了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42609978/