35

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
Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
Teisman
  • 1,318
  • 2
  • 13
  • 26

3 Answers3

67

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.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
33

How about the definition

std::atomic<int> order::c{0}
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
6

Also you can use atomic_init:

std::atomic<int> data;
std::atomic_init(&data, 0);
anhldbk
  • 4,559
  • 5
  • 29
  • 37
  • 1
    this would not be initialized during compilation? – Sergei Krivonos Aug 23 '18 at 15:30
  • Isn't static variable thread safe from c++11? I see the ++11 tag up in the question. So why do we need atomics on the first place? Why can't we just use regular int? – anicicn Jul 19 '19 at 06:48
  • @anicicn A bit late, but the initialization of the static variable is guaranteed to only run once and is thread safe. After that, it's essentially just a regular int, i.e. not thread safe. See https://stackoverflow.com/questions/8102125/is-local-static-variable-initialization-thread-safe-in-c11 – Cedric Oct 21 '22 at 10:28