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

在类中使用std::unique_ptr<std::barrier<void()>>调用arrive_and_wait()编译报错

解决std::barrier动态分配时的编译错误及实现动态修改等待线程数

错误根源分析

编译错误来自两个核心问题:

  1. 模板参数类型错误:你显式指定std::barrier<void()>,其中void()是原始函数类型,而std::barrier的模板参数要求是可存储的可调用对象类型,直接用函数类型会导致编译器无法正确存储完成回调(错误提示中_M_completion被声明为函数类型,不符合成员变量的定义规则)。
  2. 类型不匹配:带this捕获的lambda无法隐式转换为void(*)()函数指针,而std::barrier<void()>的构造函数期望第二个参数是该类型,因此触发参数不匹配错误。

修正后的代码实现

下面的代码解决了编译问题,同时支持动态修改等待线程数:

#include <iostream>
#include <barrier>
#include <memory>
#include <thread>
#include <functional>

class MyClass
{
public:
    MyClass(std::ptrdiff_t thread_count = 3)
    {
        reset_barrier(thread_count);
    }

    void run()
    {
        la_barriere->arrive_and_wait();
    }

    // 动态重置barrier,修改需要等待的线程数
    void reset_barrier(std::ptrdiff_t new_thread_count)
    {
        la_barriere = std::make_unique<std::barrier<std::function<void()>>>(
            new_thread_count,
            [this]() {
                callback1();
                callback2();
            }
        );
    }

private:
    void callback1() { std::cout << "callback1()\n"; }
    void callback2() { std::cout << "callback2()\n"; }

    std::unique_ptr<std::barrier<std::function<void()>>> la_barriere;
};

int main()
{
    MyClass test;

    std::jthread t1(&MyClass::run, &test);
    std::jthread t2(&MyClass::run, &test);
    std::jthread t3(&MyClass::run, &test);

    // 示例:修改线程数(注意:必须确保所有线程完成当前阶段的等待后再调用,否则会触发未定义行为)
    // test.reset_barrier(2);

    return 0;
}

关键修正点说明

  • 用std::function<void()>作为模板参数:它可以容纳带捕获的lambda,完美解决类型转换问题,同时保持代码的灵活性。
  • 新增reset_barrier函数:通过重新创建std::unique_ptr包裹的std::barrier实例,实现动态修改等待线程数的需求。
  • 构造函数复用初始化逻辑:调用reset_barrier完成初始化,让代码更简洁易维护。

额外优化选项(无std::function开销)

如果不需要std::function的灵活性,希望避免其运行时开销,可以让编译器自动推导lambda的类型(C++20及以上支持):

class MyClass
{
public:
    MyClass(std::ptrdiff_t thread_count = 3)
    {
        auto completion = [this]() { callback1(); callback2(); };
        la_barriere = std::make_unique<std::barrier<decltype(completion)>>(thread_count, std::move(completion));
    }

    void run() { la_barriere->arrive_and_wait(); }

    void reset_barrier(std::ptrdiff_t new_thread_count)
    {
        auto completion = [this]() { callback1(); callback2(); };
        la_barriere = std::make_unique<std::barrier<decltype(completion)>>(new_thread_count, std::move(completion));
    }

private:
    void callback1() { std::cout << "callback1()\n"; }
    void callback2() { std::cout << "callback2()\n"; }

    std::unique_ptr<std::barrier<decltype([this]() { callback1(); callback2(); })>> la_barriere;
};

内容的提问来源于stack exchange,提问作者Ibrahima Keita

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 16:23:16