Wednesday, November 5, 2025

Non-movable and non-copyable C++20 classes

On my fantastic journey implementing WinLamb v2, I’m diving deep into C++20, grasping a lot of concepts I never understood before, and having a lot of fun along the way.

One of the things that I implemented was the idea of non-copyable and non-movable classes, at first, using macros. This felt inelegant, so I implemented P2895 paper with utility classes. It ultimately failed with the nested ListView classes, so I discarded the idea too.

My final solution was to = delete move constructor, which will prevent all copy and move. The hard rules are not particularly easy to memorize, so I’ll let them here for further reference:

  1. The two copy operations are independent. Declaring copy constructor does not prevent compiler to generate copy assignment and vice versa. (Same as in C++98.)
  2. Move operations are not independent. Declaring either one of them prevents the compiler to generate the other. (Different from copy operations.)
  3. If any of the copy operations is declared, then none of the move operations will be generated.
  4. If any of the move operations is declared, then none of the copy operations will be generated.
  5. If a destructor is declared, then none of the move operations will be generated. Copy operations are still generated for reverse compatibility with C++98.
  6. Default constructor generated only when no constructor is declared. (Same as in C++98.)

Example:

class Foo {
private:
	Foo(Foo&&) = delete; // non-copyable, non-movable
};

No comments: