c++ c++11 stdatomic

c++ - Error "Uso de la función eliminada" con std:: atomic_int



c++11 stdatomic (2)

Quiero usar una variable std::atomic_int . En mi código, tengo:

#include <atomic> std::atomic_int stop = 0; int main() { // Do something }

Y esto me da un error de compilación:

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

¿Alguna idea de lo que está pasando?


En mi caso tuve de los siguientes errores (ejemplos):

• ''std :: literals'' no ha sido declarado

using namespace std::literals::string_literals;

• Error de "Uso de la función eliminada" con std :: random_device {}

std::random_device device = std::random_device{}

Compruebe cuál es su estándar de C ++ seleccionado. En mi caso en el modo de depuración había seleccionado -std = c ++ 17, TODO OK. Pero en el modo Release, seleccioné -std: c ++ 11, toneladas de errores.

Actualización probada en Clion Windows 2018.3 con compilación remota de Linux.

Usando -std = c ++ 11

Usando -std = c ++ 17

C ++ es un estándar en evolución: después de 2003 había 2011 (C ++ 11), luego 2014 (C ++ 14) y ahora tenemos 2017 (C ++ 17) y estamos trabajando para 2020 (C ++ 20 ). Muchas cosas están cambiando, están en desuso, otras características son nuevas. Si desea la última actualización, debe usar el estándar más reciente, si su software tiene un código que puede estar obsoleto, entonces tiene que usar el estándar con el que se creó.


Su código está intentando construir un std::atomic_int temporal en la RHS, luego use el constructor de copias std::atomic_int (que es delete d) para inicializar la stop , de esta manera:

std::atomic_int stop = std::atomic_int(0);

Esto se debe a que la inicialización de la copia , como lo está haciendo aquí, no es del todo equivalente a otros tipos de inicialización.

[C++11: 8.5/16]: La semántica de los inicializadores es la siguiente [..]

Si el inicializador es una lista-iniciada con paréntesis (no entre paréntesis), el objeto o la referencia se inicializa en la lista (8.5.4).

(Esto permite la opción 3, al final de esta respuesta)

[..]

Si el tipo de destino es un tipo de clase (posiblemente cv-calificado):

  • Si la inicialización es una inicialización directa , o si es una inicialización de copia donde la versión no calificada cv del tipo de origen es la misma clase que la clase de destino, o una clase derivada de la clase de destino, se consideran constructores. Los constructores correspondientes se enumeran (13.3.1.3) y el mejor se elige mediante resolución de sobrecarga (13.3). El constructor así seleccionado se llama para inicializar el objeto, con la expresión inicializadora o lista de expresiones como su argumento (s). Si no se aplica ningún constructor, o la resolución de sobrecarga es ambigua, la inicialización está mal formada.

(Esto casi describe su código, pero no del todo; la clave aquí es que, tal vez contrario a la intuición, ¡los constructores de std::atomic_int no se consideran en absoluto en su caso!)

  • De lo contrario (es decir, para los casos restantes de inicialización de copia ), las secuencias de conversión definidas por el usuario que pueden convertirse del tipo de origen al tipo de destino o (cuando se usa una función de conversión) a una clase derivada del mismo se enumeran como se describe en 13.3. 1.4, y la mejor se elige mediante resolución de sobrecarga (13.3). Si la conversión no se puede realizar o es ambigua, la inicialización no se ha realizado correctamente. La función seleccionada se llama con la expresión inicializadora como su argumento; si la función es un constructor, la llamada inicializa un temporal de la versión no calificada cv del tipo de destino. El temporal es un prvalue. El resultado de la llamada (que es el temporal para el caso del constructor) se utiliza para inicializar directamente , de acuerdo con las reglas anteriores, el objeto que es el destino de la inicialización de la copia . En ciertos casos, se permite una implementación para eliminar la copia inherente a esta inicialización directa mediante la construcción del resultado intermedio directamente en el objeto que se está inicializando; ver 12.2, 12.8.

(Este es su escenario; por lo tanto, aunque la copia puede ser eliminada, todavía debe ser posible)

  • [..]

Aquí está la solución, de todos modos; use inicialización directa o inicialización de lista :

std::atomic_int stop(0); // option 1 std::atomic_int stop{0}; // option 2 std::atomic_int stop = {0}; // option 3