Dav*_*vid 43 c++ templates template-meta-programming
鉴于以下内容:
template<typename T>
class A
{
public:
static const unsigned int ID = ?;
};
Run Code Online (Sandbox Code Playgroud)
我希望ID为每个T生成一个唯一的编译时间ID.我考虑过__COUNTER__并且增强PP库但到目前为止都没有成功.我怎样才能做到这一点?
编辑:ID必须可用作switch语句中的大小写
Edit2:基于静态方法或成员地址的所有答案都不正确.尽管它们确实创建了唯一的ID,但它们在编译时未得到解析,因此不能用作switch语句的情况.
MSN*_*MSN 11
假设符合标准的编译器(关于一个定义规则),这就足够了:
template<typename T>
class A
{
public:
static char ID_storage;
static const void * const ID;
};
template<typename T> char A<T>::ID_storage;
template<typename T> const void * const A<T>::ID= &A<T>::ID_storage;
Run Code Online (Sandbox Code Playgroud)
从C++标准3.2.5一个定义规则[basic.def.odr](大胆强调我的):
...如果D是模板并且是在多个翻译单元中定义的,那么上面列表中的最后四个要求将应用于模板定义(14.6.3)中使用的模板封闭范围中的名称,以及实例化时的从属名称(14.6.2).如果D的定义满足所有这些要求,那么程序应该表现得就像D的单个定义一样.如果D的定义不满足这些要求,则行为是不确定的.
我通常使用的是:
template<typename>
void type_id(){}
using type_id_t = void(*)();
Run Code Online (Sandbox Code Playgroud)
由于函数的每个实例都有自己的地址,因此您可以使用该地址来标识类型:
// Work at compile time
constexpr type_id_t int_id = type_id<int>;
// Work at runtime too
std::map<type_id_t, std::any> types;
types[type_id<int>] = 4;
types[type_id<std::string>] = "values"s
// Find values
auto it = types.find(type_id<int>);
if (it != types.end()) {
// Found it!
}
Run Code Online (Sandbox Code Playgroud)
可以使用此答案中的代码从字符串生成编译时哈希。
如果您可以修改模板以包含一个额外的整数并使用宏来声明变量:
template<typename T, int ID> struct A
{
static const int id = ID;
};
#define DECLARE_A(x) A<x, COMPILE_TIME_CRC32_STR(#x)>
Run Code Online (Sandbox Code Playgroud)
使用此宏进行类型声明,id 成员包含类型名称的哈希值。例如:
int main()
{
DECLARE_A(int) a;
DECLARE_A(double) b;
DECLARE_A(float) c;
switch(a.id)
{
case DECLARE_A(int)::id:
cout << "int" << endl;
break;
case DECLARE_A(double)::id:
cout << "double" << endl;
break;
case DECLARE_A(float)::id:
cout << "float" << endl;
break;
};
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当类型名称转换为字符串时,对类型名称文本的任何修改都会产生不同的 id。例如:
static_assert(DECLARE_A(size_t)::id != DECLARE_A(std::size_t)::id, "");
Run Code Online (Sandbox Code Playgroud)
另一个缺点是可能发生哈希冲突。
使用静态函数的内存地址。
template<typename T>
class A {
public:
static void ID() {}
};
Run Code Online (Sandbox Code Playgroud)
(&(A<int>::ID))将不同于(&(A<char>::ID))等等。
| 归档时间: |
|
| 查看次数: |
8410 次 |
| 最近记录: |