Hello and Welcome to my blog!
To keep my skills sharp while I am looking for work, I have been reviewing what I have learned at college.
Today I reviewed the Rule of Five in C++. The rule of five is the programming pattern that states when a class implements any of the following functions, it must implement all of them. A rule of three exist as well, the rule of five is an expanded version.
The Five functions in the rule of five are…
1 – Copy Assignment Operator
2 – Copy Constructor
3 – Deconstructor
4 – Move Assignment Operator
5 – Move Constructor
I decided to Implement the rule of five two ways, first as a Templated class and second as a Non-Templated class. 
This code was good practice, and I am planning on releasing more blogs like this one soon. All the code is below, thanks for reading my blog.
Templated Rule Of Five
template < class T >
  class RuleOfFiveTemplated {
    size_t size = 0;
    T * data = nullptr;
    public:
      // Default Constructor
      RuleOfFiveTemplated() {
        std::cout << (void * ) this << ": RuleOfFiveTemplated constructor()\n";
      }
    // Constructor Overload
    RuleOfFiveTemplated(size_t size): size(size), data(new T[size]) {
      cout << (void * ) this << ": RuleOfFiveTemplated (" << size << ") constructor\n";
    }
    // One - Assignment Operator
    RuleOfFiveTemplated & operator = (const RuleOfFiveTemplated & rhs) {
      cout << (void * ) this << ": RuleOfFiveTemplated assignment operator, size = " << size << ", rhs.size = " << rhs.size << endl;
      if (this != & rhs) {
        delete[] data;
        data = nullptr;
        size = 0;
        if (rhs.data) {
          size = rhs.size;
          try {
            data = new T[size];
            memcpy(data, rhs.data, size * sizeof(T));
          } catch (const std::bad_alloc & err) {
            cout << (void * ) this << ": RuleOfFiveTemplated Failed to copy value inside data: " << err.what() << endl;
          }
        }
      } else {
        cout << (void * ) this << ": RuleOfFiveTemplated copy assignment operator called on itself" << endl;
      }
      return *this;
    }
    // Two - Copy Constructor
    RuleOfFiveTemplated(const RuleOfFiveTemplated & rhs) {
      cout << (void * ) this << ": RuleOfFiveTemplated copy constructor, size = " << size << ", rhs.size = " << rhs.size << endl;
      data = nullptr;
      * this = rhs;
    }
    // three - Move Assignment Operator
    RuleOfFiveTemplated && operator = (RuleOfFiveTemplated && rhs) noexcept {
      cout << (void * ) this << ": RuleOfFiveTemplated move assignment operator, size = " << size << ", rhs.size = " << rhs.size << endl;
      if (this != & rhs) {
        delete[] data;
        size = rhs.size;
        data = rhs.data;
        rhs.size = 0;
        rhs.data = nullptr;
      } else {
        cout << (void * ) this << ": RuleOfFiveTemplated move assignment operator called on itself\n";
      }
      return std::move( * this);
    }
    // Four - Move Constructor
    RuleOfFiveTemplated(RuleOfFiveTemplated && rhs) noexcept {
        cout << (void * ) this << ": RuleOfFiveTemplated move constructor, size = " << size << ", rhs.size = " << rhs.size << endl;
        data = nullptr;
        * this = std::move(rhs);
      }
      // Five - De-Constructor
      ~RuleOfFiveTemplated() {
        cout << (void * ) this << ": RuleOfFiveTemplated destructor, size=" << size << "\n";
        delete[] data;
      }
    // Print
    void print() {
      cout << (void * ) this << ": size=" << size << " (" << size * sizeof(T) << " BYTES)\n";
    }
  };
Non-Templated Rule Of Five
class RuleOfFive {
	size_t size = 0;
	double* data = nullptr;
public:
	RuleOfFive() {
		cout << (void*)this << ": RuleOfFive default constructor" << endl;
	}
	RuleOfFive(double size) : size(size), data(new double[size]) {
		cout << (void*)this << ": RuleOfFive constructor overload." << endl;
	}
	// One - Copy assignment operator
	RuleOfFive& operator=(RuleOfFive& rhs) {
		cout << (void*)this << ": RuleOfFive copy assignment operator, size = " << size << ", rhs.size = " << rhs.size << endl;
		if (this != &rhs) {
			delete[] data;
			data = nullptr;
			size = 0;
			if (rhs.data) {
				size = rhs.size;
				try
				{
					data = new double[size];
					memcpy(data, rhs.data, size * sizeof(double));
				}
				catch (const std::bad_alloc&)
				{
					cout << (void*)this << ": RuleOfFive Failed to copy value inside data" << endl;
				}
			}
		}
		else {
			cout << (void*)this << ": RuleOfFive copy assignment operator called on itself" << endl;
		}
		return *this;
	}
	// Two - Copy Constructor
	RuleOfFive(RuleOfFive& rhs) {
		cout << (void*)this << ": RuleOfFive copy constructor, size = " << size << ", rhs.size = " << rhs.size << endl;
		data = nullptr;
		*this = rhs;
	}
	// Three - Move Assignment operator
	RuleOfFive&& operator=(RuleOfFive&& rhs) noexcept {
		cout << (void*)this << ": RuleOfFive move assignment operator, size = " << size << ", rhs.size = " << rhs.size << endl;
		if (this != &rhs) {
			delete[] data;
			size = rhs.size;
			data = rhs.data;
			rhs.size = 0;
			rhs.data = nullptr;
		}
		else {
			cout << (void*)this << ": RuleOfFive move assignment operator called on itself" << endl;
		}
		return std::move(*this);
	}
	// Four - Move constructor
	RuleOfFive(RuleOfFive&& rhs) noexcept {
		cout << (void*)this << ": RuleOfFive move constructor, size = " << size << ", rhs.size = " << rhs.size << endl;
		data = nullptr;
		*this = std::move(rhs);
	}
	// Five - Deconstuctor
	~RuleOfFive() {
		cout << (void*)this << ": RuleOfFive deconstuctor" << endl;
	}
	// Print
	void print()
	{
		cout << (void*)this << ": size=" << size << " (" << size * sizeof(double) << " BYTES)" << endl;
	}
};
Main Function
#include <iostream>
#include <cstring> 
using namespace std;
int main(int argc, char** argv)
{
	cout << "Rule Of Five" << endl << endl;
	// Test Default Constructors
	cout << endl << "Testing Default Constructor" << endl << "=========================================" << endl;
	RuleOfFive x; 
	cout << "x created : ";
	x.print();
	
	RuleOfFiveTemplated<double> tx;
	cout << "tx created : ";
	tx.print();
	// Test Constructor Overloads
	cout << endl << "Testing Constructor Overloads" << endl << "=========================================" << endl;
	RuleOfFive y(1000);
	cout << "y created : ";
	y.print();
	RuleOfFiveTemplated<double> ty(1000);
	cout << "ty created : ";
	ty.print();
	// Test Copy Assignment operator
	cout << endl << "Test Rule One - Copy Assignment operator" << endl << "=========================================" << endl;
	x = y;
	cout << "x : lhs : ";
	x.print();
	cout << "y : rhs : ";
	y.print();
	tx = ty;
	cout << "tx : lhs : ";
	tx.print();
	cout << "ty : rhs : ";
	ty.print();
	// Test Copy Constructor
	cout << endl << "Test Rule Two - Copy Constructor" << endl << "=========================================" << endl;
	RuleOfFive z(x);
	cout << "z created : lhs : ";
	z.print();
	cout << "x : rhs : ";
	x.print();
	RuleOfFiveTemplated<double> tz(tx);
	cout << "tz created : lhs : ";
	tz.print();
	cout << "tx : rhs : ";
	tx.print();
	// Test Move Assignment operator
	cout << endl << "Test Rule Three - Move Assignment operator" << endl << "=========================================" << endl;
	y = std::move(x);
	cout << "y : lhs : ";
	y.print();
	cout << "x : rhs : ";
	x.print();
	ty = std::move(tx);
	cout << "ty : lhs : ";
	ty.print();
	cout << "tx : rhs : ";
	tx.print();
	// Test Move Constructor
	cout << endl << "Test Rule Four - Move Constructor" << endl << "=========================================" << endl;
	RuleOfFive a(std::move(y));
	cout << "a created : lhs : ";
	a.print();
	cout << "y : rhs : ";
	y.print();
	RuleOfFiveTemplated<double> ta(std::move(ty));
	cout << "ta created : lhs : ";
	ta.print();
	cout << "ty : rhs : ";
	ty.print();
	// Test Deconstructors
	cout << endl << "Test Rule Five - Deconstructors" << endl << "=========================================" << endl;
}