#include <iostream>

using std::cout;

// Rule of three:
//   If a class requires a user-defined destructor, a user-defined copy
//   constructor, or a user-defined copy assignment operator, it almost certainly
//   requires all three.
//

// Rule of five:
//   Because the presence of a user-defined (include = default or = delete
//   declared) destructor, copy-constructor, or copy-assignment operator prevents
//   implicit definition of the move constructor and the move assignment operator,
//   any class for which move semantics are desirable, has to declare all five
//   special member functions:

struct A {
  A() = default;
  /* Constructor */
  A(const int &x) { val = x; }
  /* Copy constructor */
  A(A &other) { other.val = this->val; }
  /* Move constructor */
  A(A &&other) { other.val = this->val; }
  /* Copy assignment operator */
  A &operator=(const A &other) { return *this; }
  ~A() {}
  void print() { cout << "A(" << val << ")"; }
  int val;
};

struct B {
  B(int x) { a = A(x); }
  // B(int x) : a(x) {};
  void print() {
    cout << "B(";
    a.print();
    cout << ")";
  }
  A a;
};

int main() {
  B b(10);
  b.print();
  cout << "\n";
}

struct K {
  K() = default;
  /* Constructor */
  K(const int &x) { val = x; }
  /* Copy constructor */
  K(K &other) : K(other.val) {}
  /* Move constructor */
  K(K &&other) : K(other.val) {}
  /* Copy assignment operator */
  K &operator=(const K &other) { return *this; }
  ~K() {}
  void print() { cout << "K(" << val << ")"; }
  int val;
};