18

I'm working in a project with C++11 and I tried following code

#include <atomic>

struct A {
    std::atomic_int idx = 1;

};

int main() {
    return 0;
}

I get the compiler error

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

The same result is with C++14. When I switch to C++17 it works: wandbox

I checked cppreference for differences:

But there is no difference documented between C++14 and C++17. Why does it work with C++17 and not with C++14?

0xC0000022L
  • 20,597
  • 9
  • 86
  • 152
Thomas Sablik
  • 16,127
  • 7
  • 34
  • 62
  • What compiler/standard library/platform do you use ? – Victor Gubin Dec 05 '19 at 14:10
  • @VictorGubin I tried with Clang and GCC on Linux (Wandbox). I tried different versions. – Thomas Sablik Dec 05 '19 at 14:10
  • 1
    You can simplify the MCVE to just a local in `main` (or any function, no need for it to be `main`), instead of a struct constructor. Clang gives a similar error message, being more explicit that it's trying to use a deleted *copy* constructor instead of initializer or plain constructor: https://godbolt.org/z/SBGf9w with libc++ – Peter Cordes Dec 05 '19 at 14:14
  • @PeterCordes I wasn't sure if this error is related to class initialization. – Thomas Sablik Dec 05 '19 at 14:16
  • 3
    Getting the same error message for a simpler [mcve] proves it isn't. I wasn't sure either until I tried it. – Peter Cordes Dec 05 '19 at 14:16

1 Answers1

29

Because in C++17 there is a guaranteed RVO. In C++14 statements like Foo x = Foo(args) and Foo x (args) are technically not the same, but they are 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(); 
}

You can read more about this here: https://en.cppreference.com/w/cpp/language/copy_elision

In particular the section (since C++17):

T x = T(T(f())); // only one call to default constructor of T, to initialize x

To make C++14 code work, you can use

std::atomic_int idx { 1 };
Rinat Veliakhmedov
  • 1,021
  • 1
  • 19
  • 36