【问题标题】:Why can't I convert a lambda with a non-copyable class parameter to a std::function?为什么我不能将带有不可复制类参数的 lambda 转换为 std::function?
【发布时间】:2021-07-14 13:29:41
【问题描述】:

考虑以下无法编译的代码:

#include <mutex>
#include <functional>

class t{
    std::mutex m;
};

std::function<void(t test)> func = [](t test) {return;};

产生以下错误:

错误:从 '' 转换为非标量类型 'std::function' 请求

你能解释一下为什么这个转换不起作用吗?

PS : 现场示例:https://godbolt.org/z/7se8crf41

【问题讨论】:

  • a std::mutex 既不能复制也不能移动(传播到t),您的意思是使用std::unique_lock&lt;std::mutex&gt; 还是引用t
  • @PeterT 这解决了这个问题,但你如何解释错误信息?
  • 我认为 t 不可复制或不可移动是根本原因,但当您认为 auto f = [](t test) {return;}; f({}); 没问题时,我不明白这一点是如何解释错误的
  • @463035818_is_not_a_number std::function 的要求之一是函数类型和参数通过std::is_invokablenot the case here
  • @PeterT 你能给我指个参考吗?我没有找到那个信息。同时有一个答案正确解释了为什么 OPs 代码失败,但是你的评论让我很好奇,我发现它不仅仅是构造函数 godbolt.org/z/6qooa6o3h (注意:答案不适用的不同示例)

标签: c++ lambda


【解决方案1】:

诊断具有极大的误导性。虽然很明显 mutex 不可复制,但在提供的 sn-p 中没有请求复制 mutex!

问题的直接原因是 std::function&lt;&gt; 模板化构造函数(将在从 lambda 创建 std::function 时调用的构造函数)是 SFINAE-restricted 对象为 Callable 并提供了参数类型.

Callable 不满足,因为调用表达式试图按值传递 mutex,而 mutex 不可复制。

因此,编译器找不到任何合适的构造函数来构造std::function 对象并观察到问题诊断。

似乎无法像这样构造 std::function 有点不幸,因为您可以使用临时构造的对象调用普通函数或 lambda,例如

f(t{});

由于保证复制省略。虽然对std::mutex 这样做没有意义,但对其他不可复制、不可移动的类可能有意义。

【讨论】:

  • 这正是我一直在寻找但我没有找到的细节:) lambda 不被认为是可调用的有点奇怪。另一方面,它只是一个可以调用的奇怪的极端情况
  • @463035818_is_not_a_number 这似乎是实施质量问题。不过,它是否可以轻松修复对我来说并不是很明显。
  • 我猜 Callable 是对的。即使有人可以构造这个std::function,我也不认为可以调用它。然后选择在哪里放置惊喜和施工失败可能更好
  • @463035818_is_not_a_number 我想你应该能够像在你的例子中那样使用临时构造的互斥锁来调用它(由于保证复制省略)
  • @SergeyA 我不相信他们可以,因为std::function::operator() 按值获取,所以它会在将互斥锁转发到闭包时尝试制作副本。
猜你喜欢
  • 1970-01-01
  • 2017-04-22
  • 2020-10-28
  • 1970-01-01
  • 2014-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多