title: How to use class templates to remove boiler plate code?
body: <p>In the below example there is a base class and two derived classes. The derived classes are no different from each other but I included it simply to illustrate that there can be multiple child classes. The code creates a derived class (implicitly up-cast, think the factory design pattern) which is cloned polymorphically to a smart pointer (exactly as was done here <a href="https://stackoverflow.com/questions/43586090/clone-pattern-for-stdshared-ptr-in-c">Clone pattern for std::shared_ptr in C++</a>) and then an attribute of the class is changed to show the cloning has worked as intended. This runs great and returns the desired output "Source:4 Clone:1". I wanted to know if its possible to remover the boiler plate code though?</p>
  
  <pre><code>#include "pch.h"
  #include &lt;iostream&gt;
  
  class Node
  {
  public:
      Node(int);
      int value;
      virtual ~Node() = default;
      virtual void set_value(int) = 0;
      std::shared_ptr&lt;Node&gt; Clone() const;
  
  private:
      virtual Node * CloneImplementation() const = 0;
  };
  
  Node::Node(int VALUE) {
      value = VALUE;
  }
  
  std::shared_ptr&lt;Node&gt; Node::Clone() const {
      return std::shared_ptr&lt;Node&gt;(CloneImplementation());
  };
  
  class DerivedNode1 : public Node
  {
  public:
      DerivedNode1(int);
      void set_value(int);
      std::shared_ptr&lt;DerivedNode1&gt; Clone() const;
  
  private:
      DerivedNode1 * CloneImplementation() const override;
  };
  
  DerivedNode1::DerivedNode1(int VALUE) : Node(VALUE) {
  }
  
  std::shared_ptr&lt;DerivedNode1&gt;  DerivedNode1::Clone() const {
      return std::shared_ptr&lt;DerivedNode1&gt;(CloneImplementation());
  };
  
  DerivedNode1 * DerivedNode1::CloneImplementation() const {
      return new DerivedNode1(*this);
  };
  
  void DerivedNode1::set_value(int NEW_VALUE) {
      value = NEW_VALUE;
  }
  
  class DerivedNode2 : public Node
  {
  public:
      DerivedNode2(int);
      void set_value(int);
      std::shared_ptr&lt;DerivedNode2&gt; Clone() const;
  
  private:
      DerivedNode2 * CloneImplementation() const override;
  };
  
  DerivedNode2::DerivedNode2(int VALUE) : Node(VALUE) {
  }
  
  std::shared_ptr&lt;DerivedNode2&gt;  DerivedNode2::Clone() const {
      return std::shared_ptr&lt;DerivedNode2&gt;(CloneImplementation());
  };
  
  DerivedNode2 * DerivedNode2::CloneImplementation() const {
      return new DerivedNode2(*this);
  };
  
  void DerivedNode2::set_value(int NEW_VALUE) {
      value = NEW_VALUE;
  }
  
  std::shared_ptr&lt;Node&gt; ImplicitUpCast(int type) {
      if (type == 1) {
          return std::make_shared&lt;DerivedNode1&gt;(1);
      } else {
          return std::make_shared&lt;DerivedNode2&gt;(1);
      }
  }
  
  int main() {
      std::shared_ptr&lt;Node&gt; sourceNode1 = ImplicitUpCast(1);
      std::shared_ptr&lt;Node&gt; cloneNode1 = sourceNode1-&gt;Clone();
      sourceNode1-&gt;set_value(4);
  
      std::cout &lt;&lt; "Source: " &lt;&lt; sourceNode1-&gt;value &lt;&lt; " Clone: " &lt;&lt; cloneNode1-&gt;value;
  }
  </code></pre>
  
  <p>Making and declaring the below methods in each child class seems tedious and I wanted a workaround.</p>
  
  <pre><code>std::shared_ptr&lt;DerivedNode1&gt;  DerivedNode1::Clone() const {
      return std::shared_ptr&lt;DerivedNode1&gt;(CloneImplementation());
  };
  
  DerivedNode1 * DerivedNode1::CloneImplementation() const {
      return new DerivedNode1(*this);
  };
  </code></pre>
  
  <p>My approach was to use an 'intermediary' class template that <code>DerivedNode1</code> and <code>DerivedNode2</code> inherited from and contained both these methods. Here is my attempt.</p>
  
  <pre><code>#include "pch.h"
  #include &lt;iostream&gt;
  
  class Node
  {
  public:
      Node(int);
      int value;
      virtual ~Node() = default;
      virtual void set_value(int) = 0;
      std::shared_ptr&lt;Node&gt; Clone() const;
  
  private:
      virtual Node * CloneImplementation() const = 0;
  };
  
  Node::Node(int VALUE) {
      value = VALUE;
  }
  
  std::shared_ptr&lt;Node&gt; Node::Clone() const {
      return std::shared_ptr&lt;Node&gt;(CloneImplementation());
  };
  
  
  template&lt;class source&gt;
  class NodeExtended : public Node
  {
  public:
      NodeExtended(int);
      std::shared_ptr&lt;source&gt; Clone() const;
  private:
      source* CloneImplementation() const override;
  };
  
  template&lt;class source&gt;
  NodeExtended&lt;source&gt;::NodeExtended(int VALUE) : Node(VALUE) {
  }
  
  template&lt;class source&gt;
  std::shared_ptr&lt;source&gt; NodeExtended&lt;source&gt;::Clone() const {
      return std::shared_ptr&lt;source&gt;(CloneImplementation());
  };
  
  template&lt;class source&gt;
  source * NodeExtended&lt;source&gt;::CloneImplementation() const {
      return new source(*this);
  };
  
  class DerivedNode1 : public NodeExtended&lt;DerivedNode1&gt;
  {
  public:
      DerivedNode1(int);
      void set_value(int);
  
  };
  
  DerivedNode1::DerivedNode1(int VALUE) : NodeExtended(VALUE) {
  }
  
  void DerivedNode1::set_value(int NEW_VALUE) {
      value = NEW_VALUE;
  }
  
  class DerivedNode2 : public NodeExtended&lt;DerivedNode2&gt;
  {
  public:
      DerivedNode2(int);
      void set_value(int);
  };
  
  DerivedNode2::DerivedNode2(int VALUE) : NodeExtended(VALUE) {
  }
  
  void DerivedNode2::set_value(int NEW_VALUE) {
      value = NEW_VALUE;
  }
  
  std::shared_ptr&lt;Node&gt; ImplicitUpCast(int type) {
      if (type == 1) {
          return std::make_shared&lt;DerivedNode1&gt;(1);
      } else {
          return std::make_shared&lt;DerivedNode2&gt;(1);
      }
  }
  
  int main() {
      //std::shared_ptr&lt;Node&gt; sourceNode1 = ImplicitUpCast(1);
      //std::shared_ptr&lt;Node&gt; cloneNode1 = sourceNode1-&gt;Clone();
      //sourceNode1-&gt;set_value(4);
  
      //std::cout &lt;&lt; "Source: " &lt;&lt; sourceNode1-&gt;value &lt;&lt; " Clone: " &lt;&lt; cloneNode1-&gt;value;
  }
  
  </code></pre>
  
  <p>I receive the error 'NodeExtended::CloneImplementation': unable to match function definition to an existing declaration' on the following line</p>
  
  <pre><code>source * NodeExtended&lt;source&gt;::CloneImplementation() const {
      return new source(*this);
  };
  </code></pre>
  
  <p>I am assuming this is because Node and source are not viewed as parent and child pointers and the polymorphism breaks down because of the return type, similarly to how a smart pointer might throw an error in the situation.</p>
  
  <p>I am unsure how to continue from here. I think I don't understand class templates well enough but no tutorials really capture my use case. </p>
  
  <p>Any and all help would be appreciated.</p>
  
  <p>Edit:</p>
  
  <p>The approved answer finds the main problem but I also had to change some of the source return types to node which still gives the desired behavior. Here is the complete solution.</p>
  
  <pre><code>#include "pch.h"
  #include &lt;iostream&gt;
  
  class Node
  {
  public:
      Node(int);
      int value;
      virtual ~Node() = default;
      virtual void set_value(int) = 0;
      std::shared_ptr&lt;Node&gt; Clone() const;
  
  private:
      virtual Node * CloneImplementation() const = 0;
  };
  
  Node::Node(int VALUE) {
      value = VALUE;
  }
  
  std::shared_ptr&lt;Node&gt; Node::Clone() const {
      return std::shared_ptr&lt;Node&gt;(CloneImplementation());
  };
  
  
  template&lt;class source&gt;
  class NodeExtended : public Node
  {
  public:
      NodeExtended(int);
      std::shared_ptr&lt;source&gt; Clone() const;
  private:
      Node * CloneImplementation() const override;
  };
  
  template&lt;class source&gt;
  NodeExtended&lt;source&gt;::NodeExtended(int VALUE) : Node(VALUE) {
  }
  
  template&lt;class source&gt;
  std::shared_ptr&lt;source&gt; NodeExtended&lt;source&gt;::Clone() const {
      return std::shared_ptr&lt;source&gt;(static_cast&lt;source*&gt;(CloneImplementation()));
  };
  
  template&lt;class source&gt;
  Node * NodeExtended&lt;source&gt;::CloneImplementation() const {
      return new source(static_cast&lt;const source&amp;&gt;(*this));
  };
  
  class DerivedNode1 : public NodeExtended&lt;DerivedNode1&gt;
  {
  public:
      DerivedNode1(int);
      void set_value(int);
  
  };
  
  DerivedNode1::DerivedNode1(int VALUE) : NodeExtended(VALUE) {
  }
  
  void DerivedNode1::set_value(int NEW_VALUE) {
      value = NEW_VALUE;
  }
  
  class DerivedNode2 : public NodeExtended&lt;DerivedNode1&gt;
  {
  public:
      DerivedNode2(int);
      void set_value(int);
  };
  
  DerivedNode2::DerivedNode2(int VALUE) : NodeExtended(VALUE) {
  }
  
  void DerivedNode2::set_value(int NEW_VALUE) {
      value = NEW_VALUE;
  }
  
  std::shared_ptr&lt;Node&gt; ImplicitUpCast(int type) {
      if (type == 1) {
          return std::make_shared&lt;DerivedNode1&gt;(1);
      } else {
          return std::make_shared&lt;DerivedNode2&gt;(1);
      }
  }
  
  int main() {
      std::shared_ptr&lt;Node&gt; sourceNode1 = ImplicitUpCast(1);
      std::shared_ptr&lt;Node&gt; cloneNode1 = sourceNode1-&gt;Clone();
      sourceNode1-&gt;set_value(4);
  
      std::cout &lt;&lt; "Source: " &lt;&lt; sourceNode1-&gt;value &lt;&lt; " Clone: " &lt;&lt; cloneNode1-&gt;value;
  }
  </code></pre>