Perché il costruttore std :: atomic si comporta diversamente in C ++ 14 e C ++ 17


19

Sto lavorando a un progetto con C ++ 11 e ho provato a seguire il codice

#include <atomic>

struct A {
    std::atomic_int idx = 1;

};

int main() {
    return 0;
}

Ottengo l'errore del compilatore

error: use of deleted function 'std::__atomic_base<_IntTp>::__atomic_base(const std::__atomic_base<_IntTp>&) [with _ITp = int]'
 std::atomic_int idx = 1;
                       ^

Lo stesso risultato è con C ++ 14. Quando passo a C ++ 17 funziona: wandbox

Ho controllato cppreference per le differenze:

Ma non c'è alcuna differenza documentata tra C ++ 14 e C ++ 17. Perché funziona con C ++ 17 e non con C ++ 14?


Quale compilatore / libreria standard / piattaforma usi?
Victor Gubin,

@VictorGubin Ho provato con Clang e GCC su Linux (Wandbox). Ho provato diverse versioni.
Thomas Sablik,

1
È possibile semplificare l'MCVE solo in un locale main(o in qualsiasi funzione, non è necessario che sia main), anziché un costruttore di strutture. Clang dà un messaggio di errore simile, essendo più esplicito che sta cercando di usare un costruttore di copia cancellato invece di inizializzatore o costruttore semplice: godbolt.org/z/SBGf9w con libc ++
Peter Cordes,

@PeterCordes Non ero sicuro che questo errore fosse correlato all'inizializzazione della classe.
Thomas Sablik,

3
Ottenere lo stesso messaggio di errore per un esempio riproducibile minimo più semplice dimostra che non lo è. Non ne ero sicuro fino a quando non l'ho provato.
Peter Cordes,

Risposte:


29

Perché in C ++ 17 esiste un RVO garantito. In C ++ 14 affermazioni come Foo x = Foo(args)e Foo x (args)tecnicamente non sono la stessa cosa, ma sono in C ++ 17.

struct Foo {
    Foo() = default;
    Foo(const Foo&) = delete;
};

int main() {
    // Works in C++17 and C++20, fails in C++14 and before
    Foo foo = Foo(); 
}

Puoi leggere di più su questo qui: https://en.cppreference.com/w/cpp/language/copy_elision

In particolare la sezione (since C++17):

T x = T (T (f ())); // solo una chiamata al costruttore predefinito di T, per inizializzare x

Per far funzionare il codice C ++ 14, è possibile utilizzare

std::atomic_int idx { 1 };
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.