Is std::atomic<bool> trivially copyable?
Asked Answered
S

3

13

The following code prints whether std::atomic<bool> is trivially copyable:

#include <atomic>
#include <iostream>
#include <type_traits>

int main(){
    std::cout << std::is_trivially_copyable_v<std::atomic<bool>> << "\n";
}

It gives the following result on gcc and clang:

1

demo (gcc+clang)

But on MSVC the result is:

0

The behavior of all 3 compilers is also demonstrated here using static_assert.

I thought that trivial copyablity is defined either way by the standard.
Which compiler is right (or is it implementation specific) ?

Seizing answered 25/4 at 13:13 Comment(2)
en.cppreference.com/w/cpp/atomic/atomic states "std::atomic is neither copyable nor movable. " Now maybe for atomic bool gcc and clang have implemented a way to copy it but I'd recommand following the standardWader
godbolt.org/z/oz5EK8b5qMenagerie
U
15

See also: Is a class with deleted copy-constructor trivially copyable?

A deleted constructor is not non-trivial.

Prior to CWG1734's resolution, to be trivially copyable all copy/move constructors/assign operators needed to be trivial. This is the case for std::atomic<bool> (they are all deleted)

With the new wording, one also had to be non-deleted (and in C++20, 'eligible', as in its constraints are satisfied).

GCC and Clang do not implement this. See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96288 https://github.com/llvm/llvm-project/issues/38398

Urbanism answered 25/4 at 13:25 Comment(2)
Does it mean that MSVC is right here and gcc/glang are non-compliant ?Seizing
@Seizing Yes, MSVC is currently correct, and GCC and clang were compliant until February 2016Urbanism
C
2

The issues lies with how trivially_copyable operates. You cannot actually copy the atomic on clang:

https://godbolt.org/z/dr3q3bns5

The same applies to custom non-copyable types. So the only question is if trivially_copyable is allowed to return true for a non-copyable type. It could maybe be argued that, since the type cannot be copied, it doesn't have a non-trivial copy operation. Though my own gut feeling would be that is should give "false" - otherwise you'd have to check is_copyable as well as trivally_copyable for some cases. Somebody with more knowledge of the standard may be able to answer this - I can only say that based on Cpp-reference (https://en.cppreference.com/w/cpp/types/is_trivially_copyable), I don't see any requirements for this case.

Conservator answered 25/4 at 13:25 Comment(1)
Thanks for answering. Although I can see the reason in what you wrote, I am not positive regarding the dependency between copyability and trivial copyability. See the comments under Nifil's answer.Seizing
W
2

Followup from comments:

en.cppreference.com/w/cpp/atomic/atomic states "std::atomic is neither copyable nor movable." I'd recommend following the standard.

Also looking at gcc source code we see the copy operators are deleted.

Regarding the return value of std::is_trivially_copyable_v, I think @Juliean 's answer provides a good explanation

Wader answered 25/4 at 13:40 Comment(6)
a priori non-copyable (ie no viable copy constructor) does not imply that std::trivially_copyable must be false. "trivially copyable" is about copying by copying bytes, ie by bypassing copy constructors.Milson
Thanks for answering. But I think that as mentioned above trivial copyability is a concept separate from "normal" copyability/movablity.Seizing
@Seizing I took the definition from here en.cppreference.com/w/cpp/language/… A trivially copyable class is a class that has at least one eligible copy constructor, move constructor, copy assignment operator, or move assignment operator, each eligible copy constructor is trivial each eligible move constructor is trivial each eligible copy assignment operator is trivial each eligible move assignment operator is trivial, and has a non-deleted trivial destructor.Wader
I see now. As I am not a language lawyer, I am not sure if your interpratation is correct but I can see the reason in it.Seizing
imho you should include that quote in the answer. Note that I was not saying you are wrong. I am just saying that your answer makes a silent assumption that if a type is not copably via a copy constructor then it cannot be trivially copyable, I dont think that is obivous and that it should be part of an answer.Milson
btw as I understand the quote it would be sufficient when a class has one move constructor but no other move or copy, and if that move constructor is trivial, also the other bullets are covered. (still not saying you would be wrong, just trying to clear up my own confusion)Milson

© 2022 - 2024 — McMap. All rights reserved.