patterncppModerate
Unique type ID in C++
Viewed 0 times
typeuniquestackoverflow
Problem
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.
PS: I use this because
#include
struct Counter
{
static size_t value;
};
size_t Counter::value = 1;
template
struct TypeID : private Counter
{
static size_t value()
{
static size_t value = Counter::value++;
return value;
}
};
int main()
{
std::cout ::value() ::value() ::value() ::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).Solution
Here is my lightweight solution that involves no operations at run time:
The type id of type
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.
My original implementation is using
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.
template
struct type { static void id() { } };
template
size_t type_id() { return reinterpret_cast(&type::id); }
struct A { };
int main ()
{
cout () () () () << endl;
}The type id of type
T is nothing but the address of function type::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).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.
Code Snippets
template<typename T>
struct type { static void id() { } };
template<typename T>
size_t type_id() { return reinterpret_cast<size_t>(&type<T>::id); }
struct A { };
int main ()
{
cout << type_id<int>() << " " << type_id<int*>() << " "
<< type_id<A>() << " " << type_id<int>() << endl;
}Context
StackExchange Code Review Q#44936, answer score: 17
Revisions (0)
No revisions yet.