title: Is there a way to create unique type Id at compile time in C++
body: <p>I can create a unique type id the following way:</p>
  
  <pre class="lang-cpp prettyprint-override"><code>template&lt;typename T&gt;
  struct TypeId
  {
    static size_t value()
    {
      return reinterpret_cast&lt;size_t&gt;(&amp;TypeId&lt;T&gt;::value);
    }
  };
  
  
  auto intType = TypeId&lt;int&gt;::value();
  </code></pre>
  
  <p>It works at runtime but is there a way to do it at compile time ?
  I would like to use it in a switch statement like this:</p>
  
  <pre class="lang-cpp prettyprint-override"><code>switch (typeId)
  {
    case TypeId&lt;int&gt;::value():
      // do something
      break;
  
    case TypeId&lt;double&gt;::value():
      // do something
      break;
  
    case TypeId&lt;MyClass&gt;::value():
      // do something
      break;
  }
  </code></pre>
  
  <p>The problem here is that I cannot convert a pointer to the size_t at compile time:</p>
  
  <pre class="lang-cpp prettyprint-override"><code>template&lt;typename T&gt;
  struct TypeId
  {
    static constexpr size_t value()
    {
      return reinterpret_cast&lt;size_t&gt;(&amp;TypeId&lt;T&gt;::value);
    }
  };
  
  constexpr auto id = TypeId&lt;int&gt;::value();
  </code></pre>
  
  <p>The example above gives the following error:</p>
  
  <pre class="lang-cpp prettyprint-override"><code>error: conversion from pointer type ‘size_t (*)() {aka long unsigned int (*)()}’ to arithmetic type ‘size_t {aka long unsigned int}’ in a constant expression
     constexpr auto id = TypeId&lt;int&gt;::value();
  </code></pre>
  
  <p><strong>UPDATE</strong></p>
  
  <p>I would like to understand why returning an address is fine in a constexpr but converting it to an int is not. The following code compiles (but I cannot use pointers in a switch statement):</p>
  
  <pre class="lang-cpp prettyprint-override"><code>template&lt;typename T&gt;
  struct TypeId
  {
    static constexpr void* value()
    {
      return reinterpret_cast&lt;void*&gt;(&amp;TypeId&lt;T&gt;::value);
    }
  };
  
  constexpr void* id = TypeId&lt;int&gt;::value();
  std::cout &lt;&lt; "id: " &lt;&lt; id &lt;&lt; std::endl;
  </code></pre>