A trivially copyable class is a class:
(1.1) that has at least one eligible copy constructor, move
constructor, copy assignment operator, or move assignment operator
([special], [class.copy.ctor], [class.copy.assign]),(1.2) where each eligible copy constructor, move constructor, copy
assignment operator, and move assignment operator is trivial, and(1.3) that has a trivial, non-deleted destructor ([class.dtor]).
Now, I am not completely sure what it means. Does it mean that it is enough to have one of these?
For example a class with trivial copy constructor and copy assignment operator and explicitly deleted move constructor and move assignment operator is trivially copyable, or it means that I have non-deleted "big 6" and every one of them is trivial?
If I read this literally, having just one constructor or assignment operator should be enough. It was the case before c++20 according to cppreference.
If nothing has changed (namely I still can have deleted assignment operators or constructors) why was the wording changed? What is the difference between pre c++20 and C++20 standard meaning?
Update
The experiments (such as the one in the answer by Spencer) show that my guess was correct. What I do not understand – why change the wording in C++20 standard. Has anything actually changed?
In c++17 the definition was:
- A trivially copyable class is a class:
(6.1) where each copy constructor, move constructor, copy assignment
operator, and move assignment operator ([class.copy], [over.ass]) is
either deleted or trivial,(6.2) that has at least one non-deleted copy constructor, move
constructor, copy assignment operator, or move assignment operator,
and(6.3) that has a trivial, non-deleted destructor.
Are there any subtle differences between old definition and the new one?
>Solution :
You only need one.
#include <iostream>
#include <type_traits>
struct S
{
S() noexcept = default;
S(S const &) noexcept = default;
S(S &&) noexcept = delete;
S &operator =(S const &) noexcept = delete;
S &operator =(S &&) noexcept = default;
};
int main()
{
std::boolalpha(std::cout);
std::cout << "Trivially_copyable: " << std::is_trivially_copyable_v<S> << '\n';
return 0;
}
output for me, at Compiler Explorer:
Trivially_copyable: true
I tried this for several different compilers and C++17 and C++20 just in case, with the same output.
The wording changed to "eligible" between C++17 and C++20 because of the introduction of concepts. Look at the definition of an "eligible" copy constructor:
A copy constructor is eligible if
- it is not deleted, and
- its associated constraints, if any, are satisfied, and
- no copy constructor with the same first parameter type is more constrained than it.
C++20 constraints let the compiler make a choice between overloads with the same parameters. So in order for a copy constructor to be eligible, the "most constrained" copy constructor has to be deleted or trivial.
I’ve tried to contrive a template class that is trivially copyable for some specializations but not others, but with no success yet.