Koosha
Koosha

Reputation: 1584

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

Consider the following two lines of code:

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

In C++20, the first line initializes a to the clear state, but if I use that in C++17, a will be initialized to an unspecified state. The second line is deprecated in C++20, but in C++ 17, it initializes a to the clear state. How can I have them both in a code? I guess I should use a macro, but what is that macro exactly? And does it work for the initialization of all the other std::atomic<T> types?

Upvotes: 2

Views: 1061

Answers (3)

Nicol Bolas
Nicol Bolas

Reputation: 473212

atomic_flag is special. It is logically equivalent to an atomic<bool>, but the committee learned their lesson about having unique specializations with different behavior, so they made a completely separate type rather than a specialization of atomic for bools.

All atomic<T>s can be initialized by giving it a value of type T (so that's how you can get around the pre-C++20 value initialization nonsense). atomic_flag cannot be given a bool, since it doesn't store a bool. This is why it has that special ATOMIC_FLAG_INIT macro.

ATOMIC_FLAG_INIT may be deprecated, but it's not gone in C++20, so you are free to use it. In the relatively unlikely event that it gets removed for C++23, by then you should hopefully no longer have to support C++17.

Upvotes: 5

Koosha
Koosha

Reputation: 1584

Based on @chris comment, I think the following code will do the job:

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

The required macros are defined in either one of <memory>, <atomic>, and <version> header files. I certainly don't want to write something that is already deprecated (ie, the use is allowed, but discouraged for some reason).

Upvotes: 2

bolov
bolov

Reputation: 75688

If you need your code to work with both pre C++20 and C++20 then use ATOMIC_FLAG_INIT. It's deprecated in C++20 because it is no longer needed, but it is still supported so it will work in C++20 as it worked before.

Upvotes: 3

Related Questions