std::atomic
has deleted copy assignment operators. Hence, the following results in a compiler error:
std::atomic<int> a1, a2;
a1 = a2; // Error
I think the motivation for the deleted operators is explained e.g. in this post. So far, so good.
But I noticed, that adding volatile
causes the code to compile suddenly (live on godbolt):
volatile std::atomic<int> a1, a2;
a1 = a2; // OK
I do not really require volatile
variables for my project, so this is just out of curiosity: Is this an oversight in the C++ standard, or is this deliberate (why?)?
Note: I can get a compiler error by hacking the std::atomic
definition, either by adding
atomic & operator=(const volatile atomic &) volatile = delete;
or by removing the conversion operator operator T() const volatile noexcept
.
volatile
upfront. – Loringstd::__atomic_base<int>::operator int() const volatile
andoperator=(int)
. So it's converting toint
and back, not actually doing copy-assignment directly between atomics. IDK why that can happen withvolatile
but not without, or if the ISO standard even allows it, but it would be surprising if all 3 major compilers had the same bug. (including clang with-stdlib=libc++
, vs. gcc withlibstdc++
vs. MSVC's own headers.) – Lineationvolatile
qualifier induces the observed difference: the copy-assignment operator beingvolatile
is kind of a hack to make the compiler prefer one conversion chain to another ina1=0
. Now, has the committee foreseen the consequence OP found there? This is the question. – Tsaistd::atomic
for a custom type which implements some simple fixed point arithmetic. It is just a wrapper around an integer. I started the implementation by going through the cppreference documentation from the top. When implementing the assignments, I added a compile time unit test to check that the volatile assignment does NOT compile (simply via arequires
). I was surprised when that very test failed later on, namely once I added the conversionoperator T() const volatile
, and got curious. Hence the question. – Kremlin