When a class cannot follow the Rule of Zero, its special members should follow one of a few logical patterns.

== Why is this an issue?

Most classes should not directly handle resources, but instead, use member variables of a type that wraps individual resources and do resource handling for them:

* For memory, it can be ``++std::unique_ptr++``, ``++std::shared_ptr++``, ``++std::vector++``...
* For files, it can be ``++std::ofstream++``, ``++std::ifstream++``...
* ...

Classes that avoid directly handling resources don't need to define any of the special member functions required to properly handle resources: destructor, copy constructor, move constructor, copy assignment operator, and move assignment operator. That's because the versions of those functions provided by the compiler do the right thing automatically, which is especially useful because writing these functions correctly is typically tricky and error-prone.

Omitting all of these functions from a class is known as the Rule of Zero because no special function should be defined. This rule should apply to the vast majority of classes.

[source,cpp]
----
// Compliant: vector and unique_ptr handle the resources for us
//            we don't need to declare any special member function
class RuleOfZero {
public:
  void useResource();
  void addValue(Value const& value);
  Value getValueAtIndex(int index);
private:
  std::unique_ptr<Resource> resource = std::make_unique<Resource>();
  std::vector<Value> values;
};
----

The remaining classes that cannot use the Rule of Zero should be dedicated to managing a specific kind of resource and should follow a few logical rules:

* Copy operations only make sense when the corresponding move operations are available. That is because move operations are optimized copy operations allowed to steal resources from the source (the source is an r-value). At worst, copying is a valid implementation of move operations.

* Copy and move assignment operators only make sense when the corresponding constructor is available.

* If you need to customize one of the special member functions, it means that you directly handle resources and the other special member functions probably have a role to play in this resource management. Using `= default` only performs memberwise operations.

From these rules, we can describe three categories among which all classes should fall into.

=== Copyable classes

Like most simple classes, these classes can be copied and moved.

==== Special member functions for copyable classes

* Copy construction and move construction should both be available.

* Either copy assignment and move assignment are both available, or neither is.

==== Providing custom special member functions for copyable classes

If at least one special function needs to be customized, then:

* You need to provide a custom destructor and a custom copy constructor.

* The copy assignment needs to be either deleted or customized.

* If you can optimize the move construction, compared to the copy, you should provide a custom move constructor. Otherwise, you should just omit the move constructor.

* If the copy assignment is deleted, you need to delete the move assignment.

* If the copy assignment is customized, you need to provide a move assignment if you can optimize the move operation, compared to the copy. Otherwise, you should just omit the move assignment operator.

==== Examples of copyable classes

[source,cpp]
----
// Compliant, no copy assignment operator. Move construction will call the copy constructor.
class CountedCopyable {
  inline static int count = 0;
public:
  CountedCopyable() { count++; }
  ~CountedCopyable() { count--; }
  CountedCopyable(CountedCopyable const&) {count ++;}
  CountedCopyable& operator=(CountedCopyable const&) = delete;
};

// Compliant, all members are declared
class VerboseCopyable {
public:
  VerboseCopyable() { std::cout << "Constructor called\n"; }
  ~VerboseCopyable() { std::cout << "Destructor called\n"; }
  VerboseCopyable(VerboseCopyable const&) { std::cout << "Copy constructor called\n"; }
  VerboseCopyable& operator=(VerboseCopyable const&)  { std::cout << "Copy assignment operator called\n"; }
  VerboseCopyable(VerboseCopyable &&) { std::cout << "Move constructor called\n"; }
  VerboseCopyable& operator=(VerboseCopyable &&)  { std::cout << "Move assignment operator called\n"; }
};

----

=== Move-only classes

These are classes that cannot be copied but can be moved. For example, a class handling a resource that cannot be shared (`std::ofstream` manages an open file handle) or a class whose objects can be very costly to create.

==== Special member functions for move-only classes

* Move construction is available.

* Copy construction and copy assignment are not available.

* Move assignment may be available or not.

==== Providing custom special member functions for move-only classes

* You need to provide a custom destructor and a custom move constructor.

* The move assignment should be either deleted or customized.

==== Examples of move-only classes

[source,cpp]
----
// Compliant, the move assignment operator is implicitly deleted.
class MoveOnlyResourceHandler {
  Resource resource;
public:
  MoveOnlyResourceHandler() { resource.open(); }
  ~MoveOnlyResourceHandler() { resource.close(); }
  MoveOnlyResourceHandler(MoveOnlyResourceHandler const& other) { std::swap(other.resource, resource); }
};
----

=== Unmovable classes

These are classes that cannot be copied, nor moved. They cannot escape their current scope.

==== Special member functions for unmovable classes

All copy and move operations are deleted.

==== Examples of unmovable classes

[source,cpp]
----
// Compliant, deleting the move assignment operator implicitly deletes all implicit special member functions
class UnmovableResource {
  Resource resource;
public:
  UnmovableResource() { resource.open(); }
  ~UnmovableResource() { resource.close(); }
  UnmovableResource& operator=(UnmovableResource&&) = delete;
};
----

== Resources

=== Documentation

* {cpp} reference - https://en.cppreference.com/w/cpp/language/raii[RAII]

=== Standards

* MISRA {cpp}23 15.0.1 - "Special member functions" shall be provided appropriately

=== External coding guidelines

* {cpp} Core Guidelines - https://github.com/isocpp/CppCoreGuidelines/blob/e49158a/CppCoreGuidelines.md#c20-if-you-can-avoid-defining-default-operations-do[C.20: If you can avoid defining default operations, do]

* {cpp} Core Guidelines - https://github.com/isocpp/CppCoreGuidelines/blob/e49158a/CppCoreGuidelines.md#c21-if-you-define-or-delete-any-copy-move-or-destructor-function-define-or-delete-them-all[C.21: If you define or =delete any copy, move, or destructor function, define or =delete them all]

* {cpp} Core Guidelines - https://github.com/isocpp/CppCoreGuidelines/blob/e49158a/CppCoreGuidelines.md#c22-make-default-operations-consistent[C.22: Make default operations consistent]

ifdef::env-github,rspecator-view[]

== Comments And Links
(visible only on this page)

=== is duplicated by: S1234

=== relates to: S4963

=== on 1 Jun 2016, 17:29:31 Ann Campbell wrote:
\[~alban.auzeill], you mentioned in our discussion something about not raising false positives when the move constructor and move assignment operator are missing. I didn't really get the details of that, so it's not included here and we'll probably need to add it. Feel free to stub the details in or add them in a comment.


Also, I've changed the code samples from IntPointers to FooPointers & added a second compliant solution, which you'll probably want to take a look at.




=== on 8 Jun 2016, 17:40:06 Ann Campbell wrote:
I've made some edits [~alban.auzeill]. Take a look, please.

=== on 15 Aug 2016, 18:05:28 Ann Campbell wrote:
\[~alban.auzeill] this description is extremely long, and I'd like to shorten it by removing some or all of the {cpp} 98 and {cpp} 11 history. Given that you'll have final approval, do you mind if I go ahead?

=== on 6 Nov 2018, 17:57:54 Ann Campbell wrote:
\[~loic.joly] I find this contradictory


____ ... If you cannot find a way to implement them more efficiently than the copy operations, you can just leave them out.

Those operations work together, and letting the compiler automatically generate some of them, but not all, means that when one of those functions is called, the integrity of the resource will probably be compromised____

=== on 6 Nov 2018, 18:13:53 Loïc Joly wrote:
\[~ann.campbell.2] It's not really contradictory, because as soon as a copy constructor is written by the user, it disables the automatic generation of the move constructor, so we're not letting the compiler do anything. But I see your point, it's confusing...


With that additional information, do you have a counter proposal that is not adding too much text to this already long description?



=== on 22 Nov 2018, 15:14:57 Amélie Renard wrote:
Cases which could need an explanation :


* Destructor is defined in order to check that the object can really be destroyed (use of assert())
ex : \https://peach.sonarsource.com/project/issues?id=c-family%3Aclang&issues=AWczye3UUxytsEdVyqlH&open=AWczye3UUxytsEdVyqlH

(bad example because the class has a reference attribute - but the idea is there)


* Copy constructor and copy assignment operator are defined to keep a counter (or something like that)

* An attribute is a unique_ptr. So the user defines the copy constructor and the copy assignment operator to copy what is inside the unique_ptr. But there is no need of a destructor as the unique_ptr takes care of it.
ex : \https://peach.sonarsource.com/project/issues?id=c-family%3Aclang&issues=AWczyhmIUxytsEdVyqnR&open=AWczyhmIUxytsEdVyqnR


* Class which defines the copy constructor and/or copy assignment operator when it does not need to. This class should apply the "Rule-of-Zero".

endif::env-github,rspecator-view[]
