Unique type ID, no RTTI Following my answer to Unique type ID in C++, I have worked towards a "safer" version that I am posting here.

This is a lightweight type that can store a unique (also across compilation units) ID per type for use at runtime, without RTTI.

Instead of using a built-in type for ID representation that is also accessible to the end user, a specific class type_id_t provides the external representation of the ID and encapsulates the actual storage type (a function pointer) that is not accessible.

A helper function template call type_id&lt;T&gt;() returns a type_id_t containing the ID of type T.

Hence, the following operations are only provided:


construction only by calling type_id function.
copy/move construction, as implicitly defined
copy/move assignment, as implicitly defined
comparison operators == and != between two type_id_t's


There is no default constructor for type_id_t.

Here is the implementation:

class type_id_t
{
    using sig = type_id_t();

    sig* id;
    type_id_t(sig* id) : id{id} {}

public:
    template&lt;typename T&gt;
    friend type_id_t type_id();

    bool operator==(type_id_t o) const { return id == o.id; }
    bool operator!=(type_id_t o) const { return id != o.id; }
};

template&lt;typename T&gt;
type_id_t type_id() { return &amp;type_id&lt;T&gt;; }


It is interesting that function type_id returns a (function) pointer to itself, encapsulated into a type_id_t. No nasty type casting is necessary.

This is not a mechanism that provides runtime identification of a (polymorphic) object's type, but can be used as a low-level tool to build such functionality. I actually made this for the needs of my recent any, and then improved it.

Just for demonstration, we can store the ID of a number of types e.g. in a vector:

template&lt;typename... T&gt;
std::vector&lt;type_id_t&gt;
make_ids() { return {type_id&lt;T&gt;()...}; }


Later, we can compare the stored IDs to the ID of a given type:

template&lt;typename T, typename A&gt;
void comp_ids(const A&amp; a)
{
    for (auto i : a)
        std::cout &lt;&lt; (type_id&lt;T&gt;() == i) &lt;&lt; " ";
    std::cout &lt;&lt; std::endl;
}


and get the following:

auto ids = make_ids&lt;
    int, bool, double const&amp;, int&amp;&amp;, char(&amp;)[8],
    int, void(int), unsigned char**, std::vector&lt;void(*)()&gt;, double[4][8]
&gt;();

comp_ids&lt;int&gt;(ids);  // output: 1 0 0 0 0 1 0 0 0 0


Here is a live example.

Any comments are welcome.
The first thing I notice when looking at this code is the lack of documentation.

I would provide some more operators. Specifically I would go for operator&lt; so type_id_t is usable as key for std::map and you should think about specializing std::hash so the class can be used with hash maps.

As the code is pretty short I don't find any more to say about it. 

Btw.: Well done. I like this solution very much.