Reputation: 1358
I would like to generate identifiers for a class named order
in a thread-safe manner. The code below does not compile. I know that the atomic types do not have copy constructors, and I assume that explains why this code does not work.
Does anybody know a way to actually get this code to work? Is there an alternative approach?
#include <atomic>
#include <iostream>
class order {
public:
order() { id = c.fetch_add(1); }
int id;
private:
static std::atomic<int> c;
};
std::atomic<int> order::c = std::atomic<int>(0);
int main() {
order *o1 = new order();
order *o2 = new order();
std::cout << o1->id << std::endl; // Expect 0
std::cout << o2->id << std::endl; // Expect 1
}
Compiling the above results in the following error:
order.cpp:45:51: error: use of deleted function
‘std::atomic<int>::atomic(const std::atomic<int>&)’
In file included from order.cpp:3:0:
/usr/include/c++/4.7/atomic:594:7: error: declared here
Upvotes: 37
Views: 60992
Reputation: 28869
Since std::atomic_init
has been deprecated in C++20, here is a reimplementation which does not raise deprecation warnings, if you for some reason want to keep doing this.
static inline void sys_atomic_init(sys_atomic_t *ref, uint32_t value)
{
#ifdef __cplusplus
// atomic_init is deprecated in C++20
// use the equivalent definition from https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0883r2.pdf
atomic_store_explicit(ref, value, std::memory_order_relaxed);
#else
atomic_init(ref, value);
#endif
}
Upvotes: 0
Reputation: 4587
Also you can use atomic_init
:
std::atomic<int> data;
std::atomic_init(&data, 0);
Upvotes: 6
Reputation: 254631
I know that the atomic types do not have copy constructors, and I assume that explains why this code does not work.
Yes, the error says that quite clearly.
Does anybody know a way to actually get this code to work?
Instead of copy-initialising from a temporary, which requires an accessible copy constructor:
std::atomic<int> order::c = std::atomic<int>(0);
use direct-initialisation, which doesn't:
std::atomic<int> order::c(0); // or {0} for a more C++11 experience
You should probably prefer that anyway, unless you enjoy reading unnecessarily verbose code.
Upvotes: 71
Reputation: 409356
How about the definition
std::atomic<int> order::c{0}
Upvotes: 34