Home > Enterprise >  Attempting to reference a deleted function (copy c'tor)
Attempting to reference a deleted function (copy c'tor)

Time:01-07

I got this example of spinlock from Anthony Williams, and its something wrong with it (or I had a long day).

#include <atomic>
class spinlock 
{
    std::atomic_flag flag;
public:
    spinlock() : flag(ATOMIC_FLAG_INIT) {}
    void lock() {
        while (flag.test_and_set(std::memory_order_acquire));
    }
    void unlock(){
        flag.clear(std::memory_order_release);
    }
};

spinlock sl;
void f() 
{
    std::lock_guard lc(sl);
}

int main()
{
    f();
}

So this is enough for std::lock_guard to acquire it, but I have a compilation error.

error C2280: 'std::atomic_flag::atomic_flag(const std::atomic_flag &)': attempting to reference a deleted function

To be honest I dont see how spinlock() : flag(ATOMIC_FLAG_INIT) {} is calling a copy constructor.
I use VS2022 with C 20 standard and ATOMIC_FLAG_INIT is defined as following:

#define ATOMIC_FLAG_INIT \
    {}

Is this book example broken, or am I donning something wrong?

CodePudding user response:

ATOMIC_FLAG_INIT can only be used as follows:

std::atomic_flag v = ATOMIC_FLAG_INIT;

It is unspecified if

flag(ATOMIC_FLAG_INIT)

will work. If visual studio defines ATOMIC_FLAG_INIT as {} then your code is presumably ending up creating an std::atomic_flag with {} then calling the deleted copy constructor of flag.

If you're using c 20 you can simply remove the flag initialiser as std::atomic_flag's default constructor now initialises to false.

Without c 20 I think the only way to do this according to the standard is to use an inline initialiser:

class spinlock 
{
    std::atomic_flag flag = ATOMIC_FLAG_INIT;
public:
    void lock() {
        while (flag.test_and_set(std::memory_order_acquire));
    }
    void unlock(){
        flag.clear(std::memory_order_release);
    }
};
  •  Tags:  
  • Related