I'd like a constexpr
function that will return me a unique id for every C++ type, something like this:
using typeid_t = uintptr_t;
template <typename T>
constexpr typeid_t type_id() noexcept
{
return typeid_t(type_id<T>);
}
int main()
{
::std::cout << ::std::integral_constant<typeid_t, type_id<float>()>{} << ::std::endl;
return 0;
}
But I get an error:
t.cpp: In function 'int main()':
t.cpp:23:69: error: conversion from pointer type 'typeid_t (*)() noexcept {aka long unsigned int (*)() noexcept}' to arithmetic type 'typeid_t {aka long unsigned int}' in a constant-expression
::std::cout << ::std::integral_constant<typeid_t, type_id<float>()>{} << ::std::endl;
^
t.cpp:23:69: note: in template argument for type 'long unsigned int'
Is there a workaround or another way?
You could use some tricks as shown in this answer.
There's even a library called ctti that utilizes the same trick, it should work out of the box
static_assert(ctti::type_id<int>() != ctti::type_id<float>(), "compile-time type-id comparison");
constexpr auto hash = ctti::type_id<int>().hash();
Another way, this time involving a constexpr
function, would be to use a well known hash function like in the following example (where I used the FNV v1a):
#include <cstdint>
#include <iostream>
static constexpr uint32_t offset = 2166136261u;
static constexpr uint32_t prime = 16777619u;
constexpr uint32_t helper(uint32_t partial, const char *str) {
return str[0] == 0 ? partial : helper((partial^str[0])*prime, str+1);
}
constexpr uint32_t hash_str(const char *input) {
return helper(offset, input);
}
struct MyClassA { static constexpr uint32_t type = hash_str("MyClassA"); };
struct MyClassB { static constexpr uint32_t type = hash_str("MyClassB"); };
int main() {
std::cout << "MyClassA: " << MyClassA::type << std::endl;
std::cout << "MyClassB: " << MyClassB::type << std::endl;
}
The drawbacks:
The main advantage is that you can use this solution if you need the types to be the same over different executions (as an example, if you have to store them somewhere and use them again after a while).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With