Error with copy constructor/assignment operator for a class which has std::atomic member variable
Asked Answered
D

4

29

I have a class like below.

#include <atomic>

static const long  myValue = 0;

class Sequence
{

public:

    Sequence(long initial_value = myValue) : value_(initial_value) {}


private:

     std::atomic<long> value_;
};

int main()
{
         Sequence firstSequence;
         Sequence secondSequence = firstSequence;
         return 0;
}

I am getting compilation error like this,

test.cpp:21:36: error: use of deleted function ‘Sequence::Sequence(const Sequence&)’
test.cpp:5:7: error: ‘Sequence::Sequence(const Sequence&)’ is implicitly deleted because the default definition would be ill-formed:
test.cpp:5:7: error: use of deleted function ‘std::atomic<long int>::atomic(const std::atomic<long int>&)’

Is that the default copy constructor and assignment opertaor do not work in such case?

PS: I am using gcc version 4.6.3

Dempster answered 17/8, 2012 at 9:15 Comment(0)
F
30

You can't copy atomics with a standard copy constructor, since all loads and stores must happen explicitly. You'll have to write your own copy constructor for Sequence which does some initialization of the form value_(rhs.value_.load()) (possibly with more relaxed memory ordering).

Fairhaired answered 17/8, 2012 at 9:24 Comment(3)
Can you edit and add a compiling code example? I fail to solve this problem, I have tried: Sequence& operator=(const Sequence &other) { value_ = other.value_.load(); return *this; }Nervine
@VictorLamoine: No idea what you did, but the general approach works.Fairhaired
For more details on how you might actually write a copy-constructor (with default seq_cst for loading the source, but then avoiding the cost of an atomic store into the object under construction), see Copy constructor for classes with atomic member. Make sure this is really what you want to implement; copying around atomics is usually contrary to their purpose as shared state.Fee
F
11

Atomic has deleted copy-ctor. So copy/move-ctors in your class are deleted.

n3337 12.8/11

An implicitly-declared copy/move constructor is an inline public member of its class. A defaulted copy/ move constructor for a class X is defined as deleted (8.4.3) if X has:

— a non-static data member of class type M (or array thereof) that cannot be copied/moved because overload resolution (13.3), as applied to M’s corresponding constructor, results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor,

Fustigate answered 17/8, 2012 at 9:27 Comment(0)
S
8

Because there is no std::atomic<long int>::atomic(const std::atomic<long int>&) function, there is no way for the compiler to create a default copy constructor for the Sequence class. If you need a copy constructor for that class (and you do if you want Sequence secondSequence = firstSequence; to work) then you need to write one.

This behavior is required by the standard:

The atomic integral and address types are listed below. These types shall have standard layout. They shall have a trivial default constructor, A constexpr explicit value constructor, a deleted copy constructor, a deleted copy assignment operator, and a trivial destructor. These types shall support aggregate initialization syntax.

Sipper answered 17/8, 2012 at 9:22 Comment(0)
I
5

I'd guess that choice to delete the copy constructor in the standard was for two reasons:

  • a load/store pair is required in general. Is there any way to enforce that this would be done when you don't control the callers of std::atomic?

  • What do you do if std::atomic<> type that you were using was one for which is_lock_free() is false (ie. a mutex is required in the implementation for that size integer type)? What copy semantics do you use for the mutex initialization? A mutex that ends up implicitly copied needs to be re-initialized since it could be unluckily copied in a locked state. I'd guess that std::mutex also has a deleted copy constructor because of this, and that pushes the requirement into std::atomic too.

Insouciance answered 22/3, 2013 at 20:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.