You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过lambda向std::thread转发函数出现function类型错误如何解决?

报错根本原因
  • 模板推导规则触发隐式类型问题:传入左值函数f时,万能引用Function&&会将Function推导为函数左值引用类型int (&)(int)。
  • lambda按值捕获的类型限制:按值捕获类型为函数引用的function变量时,闭包类会生成一个和引用目标同类型的成员,也就是int(int)函数类型,C++标准不允许类的非静态成员为函数类型,直接触发类型非法错误。
修复方案

只需要修改lambda的捕获逻辑,将函数引用退化为函数指针即可,有两种常用修改方式:

  1. 用完美转发初始化捕获,自动完成类型退化:
// 把原来的捕获行[function, ...]改成下面的写法
auto lambda = [function = std::forward<Function>(function), promise = std::move(outer_promise)](Args&&... args) mutable {
  1. 显式指定类型退化:
#include <utility> // 要用到std::decay_t
auto lambda = [function = static_cast<std::decay_t<Function>>(function), promise = std::move(outer_promise)](Args&&... args) mutable {

额外优化建议

泛型代码中建议用std::invoke调用可调用对象,同时对参数做完美转发,兼容性更强:

// 把promise.set_value(function(args...))改成
promise.set_value(std::invoke(std::forward<Function>(function), std::forward<Args>(args)...));
修正后完整可运行代码
#include <future>
#include <iostream>
#include <thread>
#include <chrono>
#include <ctime>
#include <type_traits>
#include <utility>

int f(int x) {
    auto start = std::chrono::system_clock::now();
    std::time_t start_time = std::chrono::system_clock::to_time_t(start);
    std::cout << "returning " << x << " at " << std::ctime(&start_time) << std::endl;
    return x;
}

template<typename Function, typename... Args>
auto async(Function&& function, Args&&... args) {
    using ReturnType = typename std::invoke_result_t<std::decay_t<Function>, std::decay_t<Args>...>;
    std::promise<ReturnType> outer_promise;
    auto future = outer_promise.get_future();
    auto lambda = [function = std::forward<Function>(function), promise = std::move(outer_promise)]
    (Args&&... args) mutable {
        try {
            promise.set_value(std::invoke(function, std::forward<Args>(args)...));
        } catch (...) {
            promise.set_exception(std::current_exception());
        }
    };
    std::thread t0(std::move(lambda), std::forward<Args>(args)...);
    t0.detach();
    return future;
}

int main() {
    auto result1 = async(f, 1); 
    auto result2 = async(f, 2); 
    // 等待异步任务完成,避免主线程提前退出
    result1.wait();
    result2.wait();
    return 0;
}

内容的提问来源于stack exchange,提问作者Jamie C.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 05:39:01