Por que o construtor std :: atomic se comporta diferente em C ++ 14 e C ++ 17

19

Estou trabalhando em um projeto com C ++ 11 e tentei seguir o código

#include <atomic>

struct A {
    std::atomic_int idx = 1;

};

int main() {
    return 0;
}

Eu recebo o erro do 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;
                       ^

O mesmo resultado é com o C ++ 14. Quando eu mudo para o C ++ 17, ele funciona: mudo wandbox

Eu verifiquei cppreference por diferenças:

Mas não há diferença documentada entre C ++ 14 e C ++ 17. Por que funciona com o C ++ 17 e não com o C ++ 14?

Thomas Sablik
fonte
Qual compilador / biblioteca / plataforma padrão você usa?
Victor Gubin
@ VictorGubin Tentei com Clang e GCC no Linux (Wandbox). Eu tentei versões diferentes.
Thomas Sablik
11
Você pode simplificar o MCVE para apenas um local em main(ou qualquer função, não precisa ser main), em vez de um construtor struct. Clang dá uma mensagem de erro semelhante, sendo mais explícito que ele está tentando usar um apagado cópia construtor em vez de initializer ou construtor simples: godbolt.org/z/SBGf9w com libc ++
Peter Cordes
@ PeterCordes Eu não tinha certeza se esse erro está relacionado à inicialização da classe.
Thomas Sablik
3
Receber a mesma mensagem de erro para um exemplo reprodutível mínimo mais simples prova que não é. Também não tinha certeza até tentar.
Peter Cordes

Respostas:

29

Porque no C ++ 17 há um RVO garantido. No C ++ 14, as instruções gostam Foo x = Foo(args)e Foo x (args)não são tecnicamente iguais, mas estão no 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(); 
}

Você pode ler mais sobre isso aqui: https://en.cppreference.com/w/cpp/language/copy_elision

Em particular a seção (since C++17):

Tx = T (T (f ())); // apenas uma chamada para o construtor padrão de T, para inicializar x

Para fazer o código C ++ 14 funcionar, você pode usar

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