Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Trivially copyable class – what has changed in C++20?

The standard says

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]),

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

(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?

A link to c++17 definition.

In c++17 the definition was:

  1. 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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading