c – std :: function operator()和std :: forward中发生了什么?
作者:互联网
我在看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()是具有可变参数模板声明模板< 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构造在堆栈上.然后当传递给函数调用者时,首先复制a1以绑定到第一个by-value参数,然后std :: forward< A>在a1上调用,将其从by-value参数移动到lambda中.
相反,不需要复制a2来绑定功能A&参数,然后调用std :: forward< A&>(a2),它将a2作为左值而不是右值转发,并且这与A& A绑定. lambda的参数.
然后事情就会被破坏. 〜A(-1)表示使用该仪表A在移动构造状态下对A的破坏.
总之,即使ArgTypes没有像通常的完美转发习惯用法那样推断,我们仍然希望将按值ArgTypes转发为rvalues,并将Byg-ArgTypes作为lvalues转发.所以std :: forward恰好正是我们想要的.
标签:std-function,perfect-forwarding,c,c11,c14 来源: https://codeday.me/bug/20190828/1753421.html