¿Por qué std :: atomic constructor se comporta de manera diferente en C ++ 14 y C ++ 17?

19

Estoy trabajando en un proyecto con C ++ 11 e intenté seguir el código

#include <atomic>

struct A {
    std::atomic_int idx = 1;

};

int main() {
    return 0;
}

Me sale el error del compilador

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

El mismo resultado es con C ++ 14. Cuando cambio a C ++ 17 funciona: wandbox

Revisé cppreference por diferencias:

Pero no hay diferencia documentada entre C ++ 14 y C ++ 17. ¿Por qué funciona con C ++ 17 y no con C ++ 14?

Thomas Sablik
fuente
¿Qué compilador / biblioteca estándar / plataforma utiliza?
Victor Gubin
@VictorGubin Lo intenté con Clang y GCC en Linux (Wandbox). Probé diferentes versiones.
Thomas Sablik
1
Puede simplificar el MCVE a solo un local en main(o cualquier función, no es necesario que sea main), en lugar de un constructor de estructura. Clang da un mensaje de error similar, siendo más explícito que está tratando de usar un constructor de copia eliminado en lugar de un inicializador o un constructor simple: godbolt.org/z/SBGf9w con libc ++
Peter Cordes
@PeterCordes No estaba seguro si este error está relacionado con la inicialización de la clase.
Thomas Sablik
3
Obtener el mismo mensaje de error para un ejemplo reproducible mínimo más simple prueba que no lo es. Tampoco estaba seguro hasta que lo intenté.
Peter Cordes

Respuestas:

29

Porque en C ++ 17 hay un RVO garantizado. En C ++ 14, las declaraciones como Foo x = Foo(args)y Foo x (args)técnicamente no son lo mismo, pero están en 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(); 
}

Puede leer más sobre esto aquí: https://en.cppreference.com/w/cpp/language/copy_elision

En particular la sección (since C++17):

T x = T (T (f ())); // solo una llamada al constructor predeterminado de T, para inicializar x

Para que el código C ++ 14 funcione, puede usar

std::atomic_int idx { 1 };
Rinat Veliakhmedov
fuente