title: Change return type of base-class's method in its derived-classes
body: <p>I know this is not possible if the modified return value is not co-variant with the one in the base class. Still, I'd like to implement something that works that way!</p>
  
  <p>For my specific problem I need some sort of Object called <code>Node</code> with a <strong>value</strong> that can range from <code>int</code> to <code>double</code> to <code>char</code> or whatever and then I need to build a container (<code>std::vector</code>) of these <code>Node</code>s that can flexibly accept any type of <code>Node</code>.</p>
  
  <p>I build <code>Node</code> essentially as an empty class (it has something in the real code which is common for all its derived classes but is not useful for this post) and specified two types, <code>NodeInt</code> and <code>NodeDouble</code> that inherit from it.</p>
  
  <p>I then build my class <code>Container</code> with the vector as a member. Now I want to be able to loop through all the elements inside my <code>Container</code> and have their <code>value</code> returned ... how do I do this? </p>
  
  <p>This was my first attempt:</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;vector&gt;
  #include &lt;memory&gt;
  
  class Node{
  
  };
  
  class NodeChar : public Node{
  
      public:
          NodeChar(){ value = 'a'; }
          double getValue(){ return value; }
  
      private:
          double value;
  
  };
  
  class NodeInt : public Node{
  
      public:
          NodeInt(){ value = 5; }
          int getValue(){ return value; }
  
      private:
          int value;
  
  };
  
  class Collection{
  
    public:
      Collection( std::vector&lt; std::shared_ptr&lt;Node&gt; &gt; vec ){ nodeCollection = vec ; }
      void setNodes( std::vector&lt; std::shared_ptr&lt;Node&gt; &gt; vec ){ nodeCollection = vec ; }
      std::vector&lt; std::shared_ptr&lt;Node&gt; &gt; getNodes(){ return nodeCollection; }
    private:
      std::vector&lt; std::shared_ptr&lt;Node&gt; &gt; nodeCollection;    
  
  };
  
  
  int main() {
  
      NodeInt n1;
      NodeChar n2;
  
      std::vector&lt; std::shared_ptr&lt;Node&gt; &gt; vec (2) ;
      vec[0] = std::make_shared&lt;Node&gt;(n1);
      vec[1] = std::make_shared&lt;Node&gt;(n2);
  
      Collection C(vec);
  
      std::cout &lt;&lt; (C.getNodes())[0]-&gt;getValue() &lt;&lt; "  ---  " &lt;&lt; 
          (C.getNodes())[1]-&gt;getValue() &lt;&lt; std::endl;
  
      return 0;
  }
  </code></pre>
  
  <p>But of course this way gcc complains because <code>‘class Node’ has no member named ‘getValue’</code>. I need to have at least a <code>virtual</code> method there so that my program knows that each <code>Node</code> will have its own <code>getValue</code>.</p>
  
  <p>As soon as I go and try to specify its value though I need to return <strong>something</strong> ... and that's a problem!</p>
  
  <p>I solved the problem in two ways, both of which seem unnecessarily complex and ugly ...</p>
  
  <h2>ONE</h2>
  
  <p>Using a generic pointer <code>void*</code> as a return value and then casting them correctly in a second moment</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;vector&gt;
  #include &lt;memory&gt;
  
  class Node{
  
      public:
          virtual void* getValue() = 0 ;
  
  };
  
  class NodeChar : public Node{
  
      public:
          NodeChar(){ value = 'a'; }
          NodeChar( char v ){ value = v; }
  
          void* getValue(){ return &amp;value; }
  
      private:
          char value;
  
  };
  
  class NodeInt : public Node{
  
      public:
          NodeInt(){ value = 5; }
          NodeInt( int v ){ value = v; }
          void* getValue(){ return &amp;value; }
  
      private:
          int value;
  
  };
  
  class Collection{
  
    public:
      Collection( std::vector&lt; std::shared_ptr&lt;Node&gt; &gt; vec ){ nodeCollection = vec ; }
      void setNodes( std::vector&lt; std::shared_ptr&lt;Node&gt; &gt; vec ){ nodeCollection = vec ; }
      std::vector&lt; std::shared_ptr&lt;Node&gt; &gt; getNodes(){ return nodeCollection; }
    private:
      std::vector&lt; std::shared_ptr&lt;Node&gt; &gt; nodeCollection;    
  
  };
  
  
  int main() {
  
      NodeInt n1;
      NodeChar n2;
  
      std::vector&lt; std::shared_ptr&lt;Node&gt; &gt; vec (2) ;
      vec[0] = std::make_shared&lt;NodeInt&gt;(n1);
      vec[1] = std::make_shared&lt;NodeChar&gt;(n2);
  
      Collection C(vec);
  
      int* jnk1 = static_cast&lt;int*&gt;((C.getNodes())[0]-&gt;getValue());
      char* jnk2 = static_cast&lt;char*&gt;((C.getNodes())[1]-&gt;getValue());
  
      std::cout &lt;&lt; *jnk1 &lt;&lt; "  ---  " &lt;&lt; *jnk2 &lt;&lt; std::endl;
  
      // can't seem to make it work with shared pointers rather than standard int* or double* for the conversion from void*
  
      return 0;
  }
  </code></pre>
  
  <h2>TWO</h2>
  
  <p>Essentially the same but returning <code>void</code> (so nothing) but requiring as an argument a generic pointer <code>void*</code> to be updated in the method. This needs again casting it back ... </p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;vector&gt;
  #include &lt;memory&gt;
  
  class Node{
  
      public:
          virtual void getValue( void *&amp; ptr ){}
  
  };
  
  class NodeChar : public Node{
  
      public:
          NodeChar(){ value = 'a'; }
          NodeChar( double v ){ value = v; }
  
          void getValue( void *&amp; ptr ){ ptr = &amp;value; }
  
      private:
          char value;
  
  };
  
  class NodeInt : public Node{
  
      public:
          NodeInt(){ value = 5; }
          NodeInt( int v ){ value = v; }
          void getValue( void *&amp; ptr ){ ptr = &amp;value; }
  
      private:
          int value;
  
  };
  
  class Collection{
  
    public:
      Collection( std::vector&lt; std::shared_ptr&lt;Node&gt; &gt; vec ){ nodeCollection = vec ; }
      void setNodes( std::vector&lt; std::shared_ptr&lt;Node&gt; &gt; vec ){ nodeCollection = vec ; }
      std::vector&lt; std::shared_ptr&lt;Node&gt; &gt; getNodes(){ return nodeCollection; }
    private:
      std::vector&lt; std::shared_ptr&lt;Node&gt; &gt; nodeCollection;    
  
  };
  
  
  int main() {
  
      NodeInt n1;
      NodeChar n2;
  
      std::vector&lt; std::shared_ptr&lt;Node&gt; &gt; vec (2) ;
      vec[0] = std::make_shared&lt;NodeInt&gt;(n1);
      vec[1] = std::make_shared&lt;NodeChar&gt;(n2);
  
      Collection C(vec);
  
      void* jnk1 ; (C.getNodes())[0]-&gt;getValue(jnk1); 
      int* n1ptr = static_cast&lt;int*&gt;(jnk1);
      void* jnk2 ; (C.getNodes())[1]-&gt;getValue(jnk2); 
      char* n2ptr = static_cast&lt;char*&gt;(jnk2);
  
      std::cout &lt;&lt; *(n1ptr) &lt;&lt; "  ---  " &lt;&lt; *(n2ptr) &lt;&lt; std::endl;
  
      return 0;
  }
  </code></pre>
  
  <p>Is(are?) this the only way to make it work? Is there any better solution you can think of or any other way to implement the same thing (i.e. a virtual method in the base class that has different non-covariant return values depending on the derived classes)?</p>
  
  <p>EDIT:
  As mentioned in the comment another way could be using templates, but if I template Node then when I go to build a container I need to have only Node and I cannot use a mix of different specialised classes, hence (if I'm not missing something) this won't solve the problem for me!</p>