cppreference defines "Trivial move constructor":
The move constructor for class T is trivial if all of the following is true:
it is NOT user-provided (meaning, it is implicitly-defined or defaulted);
T has no virtual member functions;T has no virtual base classes;
the move constructor selected for every direct base of T is trivial;
the move constructor selected for every non-static class type (or array of class type) member of T is trivial.
cppreference also defines "Implicitly-defined move constructor":
If the implicitly-declared move constructor is NEITHER deleted NOR trivial, it is defined (that is, a function body is generated and compiled) by the compiler if odr-used or needed for constant evaluation.
The implicitly-declared move constructor must NOT be deleted is obvious. But "it must NOT be trivial" sounds confusing to me.
Doesn't it mean that if it is NOT trivial then it should be "user-provided"? And if it already is "user-provided one" then why must "implicitly-declared one" kicks in?
So what wrong here? What is the point of an implicitly-declared move constructor must NOT be trivial? Please help.
Doesn't it mean that if it is NOT trivial then it should be "user-provided"?
No. If the constructor is user-provided, it cannot be trivial. But not being trivial doesn't mean it cannot be implicitly-declared.
And if it already is "user-provided one" then why must "implicitly-declared one" kicks in?
I'm not sure what do you mean by this. A move constructor is either user-provided or implicitly-declared. If it is implicitly-declared, it can be trivial (if it meets more criteria).
Compare these two classes:
struct A {
int a;
};
struct B {
std::string b;
};
A
has implicitly-defined and trivial move constructor. B
has implicitly-declared, but non-trivial move constructor (because std::string
has user-provided move constructor).
Both are implicitly-declared, meaning I didn't provide them, but they differ in implementation. Trivial move constructor needs not to be defined - that's the meaning of the second quote you provided. Compiler can simply replace it with std::memmove
call. However, the non-trivial implicitly-declared move constructor must be defined (by the compiler) to call move constructors of each of the class members.
From yet another side, it could be presented like this:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With