c++ - std::function operator() 和 std::forward 发生了什么?

标签 c++ c++11 c++14 std-function perfect-forwarding

我正在查看 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)

解释:

a1a2在堆栈上构建。然后传入时传入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/

相关文章:

c++ - 可靠的 UDP 实现

c++ - 如何在 C++ 中返回一个二维指针数组

c++ - 在 C++ 中的类声明中初始化 const 成员

c++ - 模板和访问者模式

c++ - 使用模板解决了多重定义

c++ - 函数返回空指针而不是地址

c++ - 在 C++ 中检查 double 是否等于负无穷大的最佳方法

c++ - 在某些情况下使用 auto 作为返回类型和返回值 nullptr

c++ - Lambda 捕获作为 const 引用?

c++ - 无序关联容器什么时候发生重新散列?