我可以通过以下方式创建唯一的类型ID:
template<typename T>
struct TypeId
{
static size_t value()
{
return reinterpret_cast<size_t>(&TypeId<T>::value);
}
};
auto intType = TypeId<int>::value();
它在运行时有效,但是有没有办法在编译时完成? 我想在这样的switch语句中使用它:
switch (typeId)
{
case TypeId<int>::value():
// do something
break;
case TypeId<double>::value():
// do something
break;
case TypeId<MyClass>::value():
// do something
break;
}
这里的问题是我不能在编译时将指针转换为size_t:
template<typename T>
struct TypeId
{
static constexpr size_t value()
{
return reinterpret_cast<size_t>(&TypeId<T>::value);
}
};
constexpr auto id = TypeId<int>::value();
上面的示例给出了以下错误:
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<int>::value();
更新
我想理解为什么在constexpr中返回一个地址是可以的,但是将其转换为int却不是。编译以下代码(但是我不能在switch语句中使用指针):
template<typename T>
struct TypeId
{
static constexpr void* value()
{
return reinterpret_cast<void*>(&TypeId<T>::value);
}
};
constexpr void* id = TypeId<int>::value();
std::cout << "id: " << id << std::endl;
答案 0 :(得分:2)
这听起来像XY problem。如果要获取编译时类型信息,请使用编译时方法来执行此操作。正确的方法是使用std::is_same
。
if(std::is_same<int, T>::value) {
// do something
} else if (std::is_same<double, T>::value) {
// do something else
} // ...
此可以引起某些问题。如果您在条件中使用特定类型的方法(例如std::string::length()
),则会出现编译错误。有解决此问题的方法:
if constexpr
std::enable_if
创建依赖于类型的模板专门化reinterpret_cast
指向T
的所有指针答案 1 :(得分:0)
C ++当前没有办法自动 分配唯一的整数类型id并使其可用于编译时。
这就是为什么需要它的库使用手动类型注册的原因,例如:
template<class T> struct TypeId;
#define REGISTER_TYPE_ID(T, id_value) template<> struct TypeId<T> { static constexpr int id = id_value; };
REGISTER_TYPE_ID(bool, 1)
REGISTER_TYPE_ID(char, 2)
REGISTER_TYPE_ID(unsigned char, 3)
REGISTER_TYPE_ID(unsigned short, 4)
REGISTER_TYPE_ID(unsigned int, 5)
REGISTER_TYPE_ID(unsigned long, 6)
REGISTER_TYPE_ID(unsigned long long, 7)
REGISTER_TYPE_ID(signed char, 8)
REGISTER_TYPE_ID(signed short, 9)
REGISTER_TYPE_ID(signed int, 10)
REGISTER_TYPE_ID(signed long, 11)
REGISTER_TYPE_ID(signed long long, 12)
REGISTER_TYPE_ID(float, 13)
REGISTER_TYPE_ID(double, 14)
REGISTER_TYPE_ID(long double, 15)