C++11: écrire constructeur de déplacement atomique membre?
j'ai une classe avec une variable de membre atomique:
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
à quoi devrait ressembler le constructeur de mouvements?
Gcc 4.7 n'aime aucune de mes tentatives (comme ajouter std::move()
<!-- 2) et le filet est étonnamment calme ici...
3 réponses
Depuis que vous êtes en mouvement other
, personne d'autre n'y accèdera. Donc, la lecture de ses bar
est sûr, si elle est atomique ou pas.
atomic<T>
n'a que deux constructeurs, l'un étant par défaut ()
,(T)
. Ainsi, votre code ressemble à compiler. Si ce n'est pas le cas, que se passe-t-il si vous other.bar
T
, à l'application de l' (T)
constructeur à utiliser?
: bar( static_cast< bool >( other.bar ) )
ou égal à, et peut-être moins moche:
: bar( other.bar.load( ) )
std::atomic
n'est pas copiable ou mobiliers car le constructeur de copie est supprimé et aucun constructeur de mouvements n'est défini. Vous devez charger explicitement l'autre valeur et l'utiliser pour construire la nouvelle valeur, comme cela a été souligné dans la réponse de gustaf.
Pourquoi std::atomic
non mobile? Comme c'est une primitive de synchronisation, tous les threads doivent se synchroniser sur les mêmes données (i.e., la même adresse). Lorsque vous copiez (ou déplacez) une valeur atomique, vous devez utiliser une certaine communication protocole. Il peut être simple, comme dans votre exemple (il suffit de charger et l'utiliser pour initialiser la nouvelle atomique) mais, en général, je pense que c'est une bonne décision de conception en C++11 pour vous forcer à réfléchir. Sinon, il peut en résulter un code qui semble bien, mais a quelques problèmes de synchronisation subtile.
l'instanciation deatomic<bool>
ressemble essentiellement à ceci:
struct atomic<bool>
{
atomic<bool>(bool);
atomic<bool>( const atomic<bool>& ) = delete;
operator bool() const;
}
Donc quand vous essayez de le copier:
atomic<bool> a = ...;
atomic<bool> b(a);
supprimé Le constructeur de copie est choisi et provoque une erreur de compilation.
Vous avez besoin de convertir explicitement bool passer par operator bool() --> atomic<bool>(bool)
...
atomic<bool> a = ...;
atomic<bool> b(bool(a));