【问题标题】:Why can't I move a mutable function that contains a moved future?为什么我不能移动包含移动未来的可变函数?
【发布时间】:2015-04-24 12:21:52
【问题描述】:

我基本上是在尝试这样做:

using Type = SomeTypeThatIWantToMove;

std::promise<Type> promised_result;
std::future<Type> promised_future = promised_result.get_future();

using Callback = std::function<void()>;

Callback function_which_should_be_movable =
            [this, future_result(std::move(promised_future))]() mutable
{
    this->some_function(future_result.get());   // signature: void some_function(const Type&)
};

using ResultBuilder = std::function<Type(Callback&&)>;

// result_builder is of type ResultBuilder  
Type thingy = result_builder(std::move(function_which_should_be_movable));

MinGW 告诉我,function_which_should_be_movable 的 Move-Constructor 被删除了,因为 std::future 的 Copy-constructor 被删除了。但是,我不明白为什么编译器会尝试复制未来而不是移动它。

【问题讨论】:

  • 不幸的现实是std::function 被严重破坏了。

标签: c++ lambda mutable move-constructor


【解决方案1】:

function_which_should_be_movable 的类型为 std::function。根据cppreference

template&lt; class F &gt; function( F f );F必须满足要求 CallableCopyConstructible

您尝试用于构造 std::function 对象的 lambda 表达式不可复制,因此存在问题。

至于std::function为什么有这个要求,请看这个问题:Why the initializer of std::function has to be CopyConstructible?(这是我自己问的)。简单地说,std::function 使用的类型擦除技术将实例化F 的复制构造函数。无论您(std::function 对象的用户)是否实际使用了此复制构造函数,都会发生这种情况。

【讨论】:

  • 在这种情况下,C++14 的 Lambda 捕获表达式的意义何在?这个想法是允许这样的事情: std::unique_ptr ptr(new int(10)); auto lambda = [value = std::move(ptr)] {return *value;};那么,如果函数对象本身永远卡在它的位置上,我为什么要将某些东西移动到函数对象中,因为移动的对象会禁用复制或移动。
  • 那么你需要的不是std::function。类似的东西,但没有类型擦除。因此,您可以避免不使用复制构造函数来实例化它。
  • 构造函数对象不是问题,即使 function_which_should_be_movable 不可复制。我可以构建它并就地调用它。该错误仅在我尝试移动对象时发生。但同样:我不明白为什么删除的复制构造函数会阻止我移动该函数。移动过程中调用的复制构造函数在哪里?
  • 构造函数对象是个问题。见coliru.stacked-crooked.com/a/3a20c84f4237fbeb。构造这样的函数对象会实例化它的所有虚成员函数,并且在其中一个函数中调用所提供类型的复制构造函数。虚拟成员函数绝不会被优化出来。
猜你喜欢
  • 2019-12-14
  • 2015-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-07
  • 2018-06-21
相关资源
最近更新 更多