У меня есть класс с атомарной переменной-членом:
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
Как должен выглядеть конструктор перемещения?
Gcc 4.7 не нравится ни одна из моих попыток (например, добавление std::move()
вокруг other.bar
) и в сети здесь на удивление тихо …
Так как вы двигаетесь other
никто другой не получит к нему доступ. Так что читая из своего bar
безопасен, атомный или нет.
atomic<T>
имеет только два конструктора, один из которых по умолчанию ()
другое существо (T)
, Итак, ваш код выглядит так, как будто он должен скомпилироваться. Если этого не произойдет, что произойдет, если вы static_cast other.bar
в T
, соблюдая (T)
конструктор, который будет использоваться?
: bar( static_cast< bool >( other.bar ) )
или что равно, а может и менее безобразно
: bar( other.bar.load( ) )
std::atomic
не может быть скопирован или перемещен, потому что его конструктор копирования удален и конструктор перемещения не определен. Вы должны явно загрузить другое значение и использовать его для создания нового значения, как было указано в ответе gustaf.
Почему std::atomic
не подвижный? Так как это примитив синхронизации, все потоки должны синхронизироваться по одним и тем же данным (то есть по одному и тому же адресу). Когда вы копируете (или перемещаете) атомарное значение, вы должны использовать некоторый протокол связи. Это может быть просто, как в вашем примере (просто загрузите его и используйте его для инициализации нового атома), но в целом, я думаю, что это хорошее проектное решение C ++ 11, чтобы заставить вас задуматься об этом. В противном случае это может привести к тому, что код выглядит нормально, но имеет некоторые тонкие проблемы с синхронизацией.
Шаблон создания atomic<bool>
по сути выглядит так:
struct atomic<bool>
{
atomic<bool>(bool);
atomic<bool>( const atomic<bool>& ) = delete;
operator bool() const;
}
Поэтому, когда вы пытаетесь скопировать это:
atomic<bool> a = ...;
atomic<bool> b(a);
Конструктор удаленной копии выбран и вызывает ошибку компиляции.
Вы должны явно привести к bool, чтобы пройти operator bool() --> atomic<bool>(bool)
…
atomic<bool> a = ...;
atomic<bool> b(bool(a));