title: Resolving types in a hierarchy of classes using std::type_index
body: <p>I was looking for an alternative to the <code>Visitor</code> pattern to map behaviour for types in a hierarchy of classes and maybe allow for multiple dispatch. Any time you add a new type to a hierarchy of classes, you have to update all the supporting visitors. So I came across <code>std::type_index</code>, which according to <a href="http://en.cppreference.com/w/cpp/types/type_index" rel="nofollow">cppreference.com</a> might do the trick. I then thought, now I have to implement a <code>get_type_index</code> for every subclass, which would be related to the <code>accept</code> method of the visitor pattern. This would then only be half of the work that
  has to be done for the <code>Visitor</code> pattern. But then I saw that apparently you only have to implement a (non pure) virtual function in the base class to make the whole thing work. Below is my <a href="https://github.com/ToniBig/cpp-type-index" rel="nofollow">code</a> and I have the following question(s):</p>
  
  <ul>
  <li>Why are types mapped correctly for classes inheriting from <code>BaseVirtual</code>?</li>
  <li>How does the compiler do it and how expensive is it?</li>
  <li>Is it portable?</li>
  </ul>
  
  <pre class="lang-cpp prettyprint-override"><code>#include &lt;iostream&gt;
  #include &lt;map&gt;
  #include &lt;memory&gt;
  #include &lt;string&gt;
  #include &lt;typeindex&gt;
  
  struct Base
  {
    std::type_index get_type_index( ) const
    {
      return std::type_index( typeid(*this) );
    }
  };
  
  struct BaseVirtual
  {
    virtual std::type_index get_type_index( ) const
    {
      return std::type_index( typeid(*this) );
    }
  };
  
  template&lt;typename BaseType&gt;
  struct A : public BaseType
  {
  };
  
  template&lt;typename BaseType&gt;
  struct B : public BaseType
  {
  };
  
  template&lt;typename BaseType&gt;
  struct C : public BaseType
  {
  };
  
  int main( int argc,
            char **argv )
  {
    std::map&lt;std::type_index, std::string&gt; typeToStringMap = { { std::type_index( typeid(Base) ), "Base" }, { std::type_index( typeid(A&lt;Base&gt; ) ), "ABase" }, { std::type_index( typeid(B&lt;Base&gt; ) ), "BBase" }, { std::type_index( typeid(C&lt;Base&gt; ) ), "CBase" }, { std::type_index( typeid(BaseVirtual) ),
        "BaseVirtual" }, { std::type_index( typeid(A&lt;BaseVirtual&gt; ) ), "ABaseVirtual" }, { std::type_index( typeid(B&lt;BaseVirtual&gt; ) ), "BBaseVirtual" }, { std::type_index( typeid(C&lt;BaseVirtual&gt; ) ), "CBaseVirtual" } };
  
    A&lt;Base&gt; a;
    B&lt;Base&gt; b;
    C&lt;Base&gt; c;
  
    A&lt;BaseVirtual&gt; av;
    B&lt;BaseVirtual&gt; bv;
    C&lt;BaseVirtual&gt; cv;
  
    auto asp = std::make_shared&lt;A&lt;Base&gt;&gt;( );
    auto bsp = std::make_shared&lt;B&lt;Base&gt;&gt;( );
    auto csp = std::make_shared&lt;C&lt;Base&gt;&gt;( );
  
    auto avsp = std::make_shared&lt;A&lt;BaseVirtual&gt;&gt;( );
    auto bvsp = std::make_shared&lt;B&lt;BaseVirtual&gt;&gt;( );
    auto cvsp = std::make_shared&lt;C&lt;BaseVirtual&gt;&gt;( );
  
    A&lt;Base&gt;* ap = new A&lt;Base&gt;;
    B&lt;Base&gt;* bp = new B&lt;Base&gt;;
    C&lt;Base&gt;* cp = new C&lt;Base&gt;;
  
    A&lt;BaseVirtual&gt;* avp = new A&lt;BaseVirtual&gt;;
    B&lt;BaseVirtual&gt;* bvp = new B&lt;BaseVirtual&gt;;
    C&lt;BaseVirtual&gt;* cvp = new C&lt;BaseVirtual&gt;;
  
    std::cout &lt;&lt; typeToStringMap[a.get_type_index( )] &lt;&lt; std::endl;
    std::cout &lt;&lt; typeToStringMap[b.get_type_index( )] &lt;&lt; std::endl;
    std::cout &lt;&lt; typeToStringMap[c.get_type_index( )] &lt;&lt; std::endl;
    std::cout &lt;&lt; typeToStringMap[av.get_type_index( )] &lt;&lt; std::endl;
    std::cout &lt;&lt; typeToStringMap[bv.get_type_index( )] &lt;&lt; std::endl;
    std::cout &lt;&lt; typeToStringMap[cv.get_type_index( )] &lt;&lt; std::endl;
  
    std::cout &lt;&lt; typeToStringMap[asp-&gt;get_type_index( )] &lt;&lt; std::endl;
    std::cout &lt;&lt; typeToStringMap[bsp-&gt;get_type_index( )] &lt;&lt; std::endl;
    std::cout &lt;&lt; typeToStringMap[csp-&gt;get_type_index( )] &lt;&lt; std::endl;
    std::cout &lt;&lt; typeToStringMap[avsp-&gt;get_type_index( )] &lt;&lt; std::endl;
    std::cout &lt;&lt; typeToStringMap[bvsp-&gt;get_type_index( )] &lt;&lt; std::endl;
    std::cout &lt;&lt; typeToStringMap[cvsp-&gt;get_type_index( )] &lt;&lt; std::endl;
  
    std::cout &lt;&lt; typeToStringMap[ap-&gt;get_type_index( )] &lt;&lt; std::endl;
    std::cout &lt;&lt; typeToStringMap[bp-&gt;get_type_index( )] &lt;&lt; std::endl;
    std::cout &lt;&lt; typeToStringMap[cp-&gt;get_type_index( )] &lt;&lt; std::endl;
    std::cout &lt;&lt; typeToStringMap[avp-&gt;get_type_index( )] &lt;&lt; std::endl;
    std::cout &lt;&lt; typeToStringMap[bvp-&gt;get_type_index( )] &lt;&lt; std::endl;
    std::cout &lt;&lt; typeToStringMap[cvp-&gt;get_type_index( )] &lt;&lt; std::endl;
  }
  </code></pre>
  
  <p><strong>Output:</strong></p>
  
  <pre><code>Base
  Base
  Base
  ABaseVirtual
  BBaseVirtual
  CBaseVirtual
  Base
  Base
  Base
  ABaseVirtual
  BBaseVirtual
  CBaseVirtual
  Base
  Base
  Base
  ABaseVirtual
  BBaseVirtual
  CBaseVirtual
  </code></pre>