考虑以下两行代码。
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中可以像以前一样工作。
atomic_flag
是特殊的。它在逻辑上等同于一个 atomic<bool>
但是,委员会吸取了关于具有不同行为的独特专业的教训,所以他们制作了一个完全独立的类型,而不是一个特殊化的 atomic
对于 bool
s.
所有 atomic<T>
s可以通过给它一个类型为 T
(所以这样才能绕过C++20之前的值初始化废话)。atomic_flag
不能给一个 bool
,因为它没有存储一个 bool
. 这就是为什么它有特殊的 ATOMIC_FLAG_INIT
宏。
ATOMIC_FLAG_INIT
可能被废弃了,但在C++20中并没有消失,所以你可以自由使用它。在 大概率事件 它在C++23中被删除了,到时候你应该就不用再支持C++17了。
根据 @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>
头文件。我当然不希望写一些已经被废弃的东西(即允许使用,但由于某些原因不鼓励使用)。