Unique type ID in C++ I need to have an unique ID for any type in C++ for a variant type. Is this code reliable for getting the ID? I don't care to have same ID for same type between multiple runs. Sorry for typos/formatting, I wrote the code on my phone and tested on Ideone.

#include &lt;iostream&gt;

struct Counter
{
    static size_t value;
};

size_t Counter::value = 1;

template&lt;typename T&gt;
struct TypeID : private Counter
{
    static size_t value()
    {
        static size_t value = Counter::value++;
        return value;
    }
};

int main()
{
    std::cout &lt;&lt; TypeID&lt;int&gt;::value() &lt;&lt; " " &lt;&lt; TypeID&lt;int*&gt;::value() &lt;&lt; " " &lt;&lt; TypeID&lt;Counter&gt;::value() &lt;&lt; " " &lt;&lt; TypeID&lt;int&gt;::value();

return 0;
}


PS: I use this because std::type_index/std::type_info::hash may have the same value for different types (probably not in practice).
Here is my lightweight solution that involves no operations at run time:

template&lt;typename T&gt;
struct type { static void id() { } };

template&lt;typename T&gt;
size_t type_id() { return reinterpret_cast&lt;size_t&gt;(&amp;type&lt;T&gt;::id); }

struct A { };

int main ()
{
    cout &lt;&lt; type_id&lt;int&gt;() &lt;&lt; " " &lt;&lt; type_id&lt;int*&gt;() &lt;&lt; " "
         &lt;&lt; type_id&lt;A&gt;() &lt;&lt; " " &lt;&lt; type_id&lt;int&gt;() &lt;&lt; endl;
}


The type id of type T is nothing but the address of function type&lt;T&gt;::id, re-interpreted as a number. Being a static method, there is a unique such function per type. These addresses are assigned by the linker (I think), so they remain constant between different runs. The overhead in executable size is linear in the number of type ids requested (that is, the number of instantiations of type&lt;T&gt;).

This solution has been tested in gcc and clang, and works correctly across different compilation units, i.e. you get the same unique type id for the same type in different compilation units. However, I cannot quite explain why/how this happens.

type_id() is easily inlined, so has no run-time cost. However, since it contains reinterpret_cast (and since the function address is not known to the compiler), it cannot be made constexpr. But I don't see this as a problem: if you want to use something e.g. as a template argument, you can use the type directly instead of its id. The id is for run-time use only.

My original implementation is using const void* as the return type of type_id(), so I know it has the same size as any pointer. I adapted it to size_t to fit the question. I think this is still safe, but I can't see why const void* wouldn't be fair enough.

By the way, because I haven't used it very much, I'd be happy to hear if there may be problems with this approach.