C++20前后std::atomic的初始化

Initialization of std::atomic before and after C++20

考虑以下两行代码:

std::atomic_flag a { };                // Since C++20
std::atomic_flag a = ATOMIC_FLAG_INIT; // Until C++20

在 C++20 中,第一行将 a 初始化为清除状态,但如果我在 C++17 中使用它,a 将被初始化为未指定状态。第二行在 C++20 中已弃用,但在 C++17 中,它将 a 初始化为清除状态。我怎样才能将它们都放在代码中?我想我应该使用宏,但那个宏到底是什么?它是否适用于所有其他 std::atomic<T> 类型的初始化?

如果您需要您的代码同时适用于 C++20 之前的版本和 C++20,请使用 ATOMIC_FLAG_INIT。它在 C++20 中已被弃用,因为不再需要它,但它仍然受支持,因此它将像以前一样在 C++20 中工作。

根据@chris 的评论,我认为以下代码可以完成这项工作:

#if __has_cpp_attribute(__cpp_lib_atomic_value_initialization)
std::atomic_flag a { };
#else
std::atomic_flag a = ATOMIC_FLAG_INIT;
#endif

所需的宏在 <memory><atomic><version> 头文件之一中定义。我当然不想写一些已经被弃用的东西(即允许使用,但出于某种原因不鼓励使用)。

atomic_flag很特别。它在逻辑上等同于 atomic<bool>,但委员会吸取了关于具有不同行为的独特专业化的教训,因此他们制作了一个完全独立的类型而不是 atomic 的专业化 bools .

所有 atomic<T> 都可以通过给它一个 T 类型的值来初始化(这样你就可以绕过 C++20 之前的值初始化废话)。 atomic_flag 不能被赋予 bool,因为它不存储 bool。这就是为什么它有那个特殊的 ATOMIC_FLAG_INIT 宏。

ATOMIC_FLAG_INIT 可能已被弃用,但它在 C++20 中并未消失,因此您可以自由使用它。在 relatively unlikely event 中为 C++23 删除了它,到那时你应该不再需要支持 C++17。