Why does std::atomic compile since C++17 even with a deleted copy constructor?
Asked Answered
T

1

11

I have a simple code:

#include <atomic>

int main()
{
    std::atomic<int> a = 0;
}

This code compiles fine with GCC 11.1.0 with -std=c++17, but fails with -std=c++14 and -std=c++11.

using a deleted function std::atomic::atomic(const std::atomic&)

Why is that? In C++17 class std::atomic still doesn't have a copy constructor. Why is this code valid for -std=c++17?

Of course I know that the preferred style is to use {}, but I'm just curious why the code above compiles fine since C++17.

Tripoli answered 10/7, 2021 at 13:43 Comment(0)
N
14

Since C++17 such copy elision is guaranteed. For std::atomic<int> a = 0;, a is required to be initialized from 0 directly.

Note: the rule above does not specify an optimization: C++17 core language specification of prvalues and temporaries is fundamentally different from that of the earlier C++ revisions: there is no longer a temporary to copy/move from. Another way to describe C++17 mechanics is "unmaterialized value passing": prvalues are returned and used without ever materializing a temporary.

Before C++17, even though the copy/move operation (initializing a from the temporary std::atomic<int> which initialized from 0) might be optimized out (in the copy initialization), the copy/move constructor is still required to be accessible.

The last step is usually optimized out and the result of the conversion is constructed directly in the memory allocated for the target object, but the appropriate constructor (move or copy) is required to be accessible even though it's not used. (until C++17)

Nod answered 10/7, 2021 at 13:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.