C ++ 11: написать конструктор перемещения с атомарным тегом & lt; bool & gt; член?

У меня есть класс с атомарной переменной-членом:

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) и в сети здесь на удивление тихо …

24

Решение

Так как вы двигаетесь otherникто другой не получит к нему доступ. Так что читая из своего bar безопасен, атомный или нет.

atomic<T> имеет только два конструктора, один из которых по умолчанию ()другое существо (T), Итак, ваш код выглядит так, как будто он должен скомпилироваться. Если этого не произойдет, что произойдет, если вы static_cast other.bar в T, соблюдая (T) конструктор, который будет использоваться?

: bar( static_cast< bool >( other.bar ) )

или что равно, а может и менее безобразно

: bar( other.bar.load( ) )

15

Другие решения

std::atomic не может быть скопирован или перемещен, потому что его конструктор копирования удален и конструктор перемещения не определен. Вы должны явно загрузить другое значение и использовать его для создания нового значения, как было указано в ответе gustaf.

Почему std::atomic не подвижный? Так как это примитив синхронизации, все потоки должны синхронизироваться по одним и тем же данным (то есть по одному и тому же адресу). Когда вы копируете (или перемещаете) атомарное значение, вы должны использовать некоторый протокол связи. Это может быть просто, как в вашем примере (просто загрузите его и используйте его для инициализации нового атома), но в целом, я думаю, что это хорошее проектное решение C ++ 11, чтобы заставить вас задуматься об этом. В противном случае это может привести к тому, что код выглядит нормально, но имеет некоторые тонкие проблемы с синхронизацией.

25

Шаблон создания 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));
1
По вопросам рекламы [email protected]