I've got a class with an atomic member variable:
struct Foo
{
std::atomic<bool> bar;
/* ... lots of other stuff, not relevant here ... */
Foo()
: bar( false )
{}
/* Trivial implementation fails in gcc 4.7 with:
* error: use of deleted function ‘std::atomic<bool>::atomic(const td::atomic<bool>&)’
*/
Foo( Foo&& other )
: bar( other.bar )
{}
};
Foo f;
Foo f2(std::move(f)); // use the move
How should be move constructor look like?
Gcc 4.7 doesn't like any of my attempts (like adding std::move()
around the other.bar
) and the net is surprisingly quiet here...
Since you're moving other
, no one else will access it. So reading from its bar
is safe, wether it's atomic or not.
atomic<T>
only has two constructors, one being the default ()
, the other being (T)
. So, your code looks like it should compile. If it doesn't, what happens if you static_cast other.bar
to T
, enforcing the (T)
constructor to be used?
: bar( static_cast< bool >( other.bar ) )
or which is equal to, and perhaps less ugly:
: bar( other.bar.load( ) )
std::atomic
is not copyable or movable because its copy constructor is deleted and no move constructor is defined. You have to explicitly load the other value and use it construct the new value, as it was pointed out in gustaf's answer.
Why is std::atomic
not movable? As it is a synchronization primitive, all threads have to synchronize on the same data (i.e., the same address). When you copy (or move) an atomic value, you have to use some communication protocol. It may be simple, as in your example (just load it and use it to initialize the new atomic) but, in general, I think it is a good design decision by C++11 to force you to think about it. Otherwise, it may result in code that looks fine, but has some subtile synchronization issues.
The template instantiation of atomic<bool>
essentially looks like this:
struct atomic<bool>
{
atomic<bool>(bool);
atomic<bool>( const atomic<bool>& ) = delete;
operator bool() const;
}
So when you try to copy it:
atomic<bool> a = ...;
atomic<bool> b(a);
The deleted copy constructor is chosen and causes a compile error.
You need to explicitly cast to bool to go through operator bool() --> atomic<bool>(bool)
...
atomic<bool> a = ...;
atomic<bool> b(bool(a));