title: C++ Value semantics, Immutablity and Inheritance
body: <p><a href="https://stackoverflow.com/questions/18709647/shared-pointer-to-an-immutable-type-has-value-semantics">Shared pointer to an immutable type has value semantics</a></p>
  
  <p>I am trying to create a builder class which has value semantics which looks like something like this</p>
  
  <pre><code>class Pipeline {
  public:
    Pipeline(
       const std::string&amp; name, 
       std::optional&lt;size_t&gt; limitIn,
       std::optional&lt;size_t&gt; limitOut) {...}
  
    shared_ptr&lt;const Pipeline&gt; limitInput(size limit) const { 
      return make_shared&lt;Pipeline&gt;(name_, size_, limit, limitOut_) ;
    }
  
    shared_ptr&lt;const Pipeline&gt; limitOutput(size limit) const { 
      return make_shared&lt;Pipeline&gt;(name_, size_, limitInput_, limit) ;
    }
  private:
    const string name_;
    const size_t limitInput_;
    const size_t limitOutput_;
  };
  </code></pre>
  
  <p>Since member variables are const, shared_ptr is essentially immutable.</p>
  
  <p>However this pattern breaks down when I need to add inheritance. For ex:</p>
  
  <pre><code>
  class Pipeline {
   ...
  
   virtual void doSomething() const = 0;
  }
  </code></pre>
  
  <p>Now in any of the methods (say in limitOutput) when I need to create a new instance of Pipeline I would need to know about the derived class as well since I cannot create an instance of Pipeline anymore. One way I can think of to solve this is to add another virtual method to initialize the object.</p>
  
  <pre><code>class Pipeline {
   ...
  
   virtual shared_ptr&lt;Pipeline&gt; create(const std::string&amp; name, 
       std::optional&lt;size_t&gt; limitIn,
       std::optional&lt;size_t&gt; limitOut) const = 0;
  }
  
  class SpecialPipeline  : public Pipeline {
   ...
  
   virtual shared_ptr&lt;Pipeline&gt; create(const std::string&amp; name, 
       std::optional&lt;size_t&gt; limitIn,
       std::optional&lt;size_t&gt; limitOut) const override {
      return make_shared&lt;SpecialPipeline&gt;(name, limitIn, limitOut);
   }
  };
  </code></pre>
  
  <p>Now all methods would just defer to this</p>
  
  <pre><code>  shared_ptr&lt;const Pipeline&gt; limitInput(size limit) const { 
      return create(name_, size_, limit, limitOut_);
    }
  </code></pre>
  
  <p>While this works I personally feel it isn't elegant, involves duplication construction and doesn't feel idiomatic. How would one go about implementing this ? Any feedback would be appreciated.</p>