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

如何可移植地声明不带完成函数的std::barrier?

跨编译器通用的无完成函数std::barrier声明方式

我在尝试多种方式声明不带完成函数的std::barrier时,始终没找到跨编译器通用的单行写法,尤其疑惑MSVC在看似标准的代码中触发N4861静态断言。尝试的代码如下:

#include <barrier>
#include <functional>

class Class {
    // 缺少模板参数
    // std::barrier my_barrier1;
    
    // MSVC触发N4861静态断言
    // std::barrier<void(*)(void) noexcept> my_barrier2;
    
    // MSVC触发N4861静态断言
    // std::barrier<std::function<void()>> my_barrier3;
    
    // std::function不支持noexcept修饰符
    // std::barrier<std::function<void() noexcept>> my_barrier3b;
    
    // 仅在MSVC编译通过,跨编译器不可用
    // std::barrier<std::_No_completion_function> my_barrier4;
    
    // 复制MSVC内部实现,跨编译器可用
    struct _No_completion_function {
        void operator()() noexcept {}
    };
    std::barrier<_No_completion_function> my_barrier5;
};

int main() {
    return 0;
}

更简便的可移植写法

有两种更简洁的跨编译器通用方式:

  • 单行匿名函数类型写法:
    利用C++11的lambda表达式类型直接作为模板参数,同时注意std::barrier没有默认构造函数,必须指定同步线程数:

    std::barrier<decltype([]() noexcept {})> my_barrier{1};
    

    这个写法无需额外定义结构体,lambda的operator()天然满足noexcept,且类型可复制、可默认构造,能在GCC、Clang、MSVC中正常编译。

  • 复用空完成函数类型:
    若需要在多个地方使用,可定义一个通用的空完成函数结构体(比复制MSVC内部实现更规范):

    struct EmptyCompletion {
        void operator()() noexcept {}
    };
    // 类内声明并初始化
    std::barrier<EmptyCompletion> my_barrier{1};
    

关于MSVC的N4861静态断言原因

MSVC的std::barrier实现对完成函数类型有三个核心要求:

  1. 可默认构造
  2. 可复制构造
  3. 调用时必须是noexcept的

你尝试的几种写法失败原因:

  • void(*)(void) noexcept:函数指针默认构造会得到空指针,MSVC禁止用空指针作为完成函数(避免调用未定义行为),触发断言;
  • std::function<void()>:std::function的operator()不保证noexcept,即使存储的函数是noexcept,也不符合要求;
  • std::_No_completion_function:是MSVC私有实现细节,其他编译器不识别,无法移植。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 21:46:20