Reputation: 5793
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
Upvotes: 30
Views: 23046
Reputation: 8260
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.
Upvotes: 5
Reputation: 477150
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).
Upvotes: 31
Reputation: 55897
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,
Upvotes: 11
Reputation: 182779
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.
Upvotes: 8