如何可移植地声明不带完成函数的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实现对完成函数类型有三个核心要求:
- 可默认构造
- 可复制构造
- 调用时必须是
noexcept的
你尝试的几种写法失败原因:
void(*)(void) noexcept:函数指针默认构造会得到空指针,MSVC禁止用空指针作为完成函数(避免调用未定义行为),触发断言;std::function<void()>:std::function的operator()不保证noexcept,即使存储的函数是noexcept,也不符合要求;std::_No_completion_function:是MSVC私有实现细节,其他编译器不识别,无法移植。
内容的提问来源于stack exchange,提问作者bers
相关产品推荐
相关产品推荐

