我想要一种通用的方法来为任何C ++用户定义的类型创建唯一的编译时标识符 例如:
unique_id<my_type>::value == 0 // true
unique_id<other_type>::value == 1 // true
我已经设法使用预处理器元编程实现这样的东西,问题是,序列化不一致。例如,如果首先使用unique_id
实例化类模板other_type
,那么我的程序的先前版本中的任何序列化都将失效。
我已经搜索了这个问题的解决方案,如果唯一值是编译时常量,我找到了几种使用非一致序列化实现它的方法。如果使用 RTTI 或类似方法(如boost::sp_typeinfo
),则唯一值显然不是编译时常量,并且存在额外开销。针对此问题的临时解决方案是,以正确的顺序在单独的头中实例化所有unique_id,但这会导致额外的维护和样板代码,这与使用enum unique_id{my_type, other_type};
没有什么不同。
这个问题的一个很好的解决方案是使用用户定义的文字,遗憾的是,据我所知,目前没有编译器支持它们。使用udl的语法为'my_type'_id; 'other_type'_id;
。
我希望有人知道允许在C ++中使用当前标准(C ++ 03 / C ++ 0x)实现可序列化的唯一标识符的技巧,如果它适用于最新的稳定MSVC,我会很高兴GNU-G ++编译器,虽然我希望如果有解决方案,但它不可移植。
我想说清楚,使用mpl::set
或类似mpl::vector
和过滤等结构,并不能解决这个问题,因为元集/向量的范围是有限的并且实际上导致比预处理器元编程更多的问题。
答案 0 :(得分:2)
前段时间我向我的一个项目添加了一个构建步骤,这允许我在C ++源文件中编写@script_name(args)
并将其自动替换为相关脚本的输出,例如{{1 }或./script_name.pl args
。
您可能不愿意将语言污染为非标准C ++,但您只需编写./script_name.py args
即可获取类名的唯一整数哈希,无论构建顺序如何且没有需要明确的实例化。
这只是众多可能的非标准解决方案中的一种,我认为这个解决方案相当简洁。目前没有很好的方法可以在你的类上强加一个任意的,一致的排序,而不是明确地指定它,所以我建议你简单地放弃并进入显式的实例化路径;集中信息并没有什么不妥,但正如你所说,它与枚举并没有什么不同,这就是我在这种情况下实际使用的。
答案 1 :(得分:1)
数据的持久性是一个非常有趣的问题。
我的第一个问题是:你真的想要序列化吗?如果您愿意调查替代方案,请跳到下一部分。
如果你还在那里,我认为你还没有给出typeid
解决方案。
// static detection
template <typename T>
size_t unique_id()
{
static size_t const id = some_hash(typeid(T)); // or boost::sp_typeinfo
return id;
}
// dynamic detection
template <typename T>
size_t unique_id(T const& t)
{
return some_hash(typeid(t)); // no memoization possible
}
注意:我使用本地静态来避免初始化问题的顺序,以防在输入main
之前需要此值
它与你的unique_id<some_type>::value
非常相似,即使它是在运行时计算的,它只计算一次,然后结果(用于静态检测)被记忆以备将来调用。
另请注意,它完全通用:无需为每种类型显式编写函数。
这可能看起来很愚蠢,但序列化的问题是你在类型及其表示之间有一对一的映射:
对于持久保存,我通常建议使用专用BOM。将保存的数据视为未来自我的信息。我通常会更加努力,并提出了令人敬畏的Google Proto Buffer库:
答案 2 :(得分:0)
非常确定你必须实现自己的扩展才能实现这一点,我没有看到也没有听说过编译时这样的构造。 MSVC为预处理器提供__COUNTER__
,但我知道没有等效的模板。