title: Most efficient safe way to cast std::map<int, std::shared_ptr<Base>> to std::map<int, std::shared_ptr<Derived>>
body: <p>We currently store several different collections of data models like so:</p>
  
  <pre><code>std::map&lt;std::string, std::map&lt;int64_t, std::shared_ptr&lt;DataObject&gt;&gt;&gt; models;
  </code></pre>
  
  <p>The string maps to a known list of types and this is all dealt with by serialization. The nested map contains a collection of "Object Id" and associated (deserialized) std::shared_ptr&lt;DataObject&gt;</p>
  
  <p>DataObject is a base class which we have several types derived from.</p>
  
  <p>We have a method to get all DataObjects of a given type:</p>
  
  <pre><code>static std::map&lt;int64_t, std::shared_ptr&lt;DataObject&gt;&gt; *getAll(std::string type);
  </code></pre>
  
  <p>This simply returns a pointer to the map at a given "type" key.</p>
  
  <p>Today I encountered a code review to add the following which I believe invokes UB but seems to function. This has me a little nervous and looking for an efficient solution:</p>
  
  <pre><code>template &lt;typename M&gt;
  static std::map&lt;int64_t, std::shared_ptr&lt;M&gt;&gt; *getAll(const std::string &amp;type) {
      auto castObjectMap = reinterpret_cast&lt;std::map&lt;int64_t, std::shared_ptr&lt;M&gt;&gt;*&gt;(getAll(type));
      return castObjectMap;
  }
  </code></pre>
  
  <p>The benefit to casting like this is that it involves no looping or copying (as far as I can tell), it's a simple pointer cast. That's fantastic. But I don't think it's portable or safe, though I don't know what the best portable and safe alternative would be.</p>
  
  <p>I have a simplified version of a toy version of this question below, it does actually spit out the correct output as expected:</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;memory&gt;
  #include &lt;string&gt;
  #include &lt;map&gt;
  
  using namespace std;
  
  struct Base {
      Base(){}
      virtual ~Base(){}
  
      Base(int u):x(u){}
  
      int x = 0;
  };
  
  struct Derived : public Base {
      Derived(){}
      Derived(int u, int v):Base(u),y(v){}
      int y = 0;
  };
  
  int main() {
      map&lt;int, shared_ptr&lt;Base&gt;&gt; test {
          {0, make_shared&lt;Derived&gt;(2, 3)},
          {1, make_shared&lt;Derived&gt;(4, 5)},
          {2, make_shared&lt;Derived&gt;(6, 7)}
      };
  
      map&lt;int, shared_ptr&lt;Derived&gt;&gt; *castVersion = reinterpret_cast&lt;map&lt;int, shared_ptr&lt;Derived&gt;&gt;*&gt;(&amp;test);
  
      for(auto&amp;&amp;kv : *castVersion){
          cout &lt;&lt; kv.first &lt;&lt; ": " &lt;&lt; kv.second-&gt;x &lt;&lt; ", " &lt;&lt; kv.second-&gt;y &lt;&lt; std::endl;
      }
      return 0;
  }
  </code></pre>
  
  <p>My question is if there's a good way to do this which doesn't involve a lot of copying, or if there's a clean way to do so at least. We are using C++17 presently.</p>