[英]Creating serializeable unique compile-time identifiers for arbitrary UDT's
我想要一种通用的方法来为任何C ++用户定义的类型创建唯一的编译时标识符。
例如:
unique_id<my_type>::value == 0 // true
unique_id<other_type>::value == 1 // true
我已经设法使用预处理器元编程实现这样的事情,问题是,序列化不一致。 例如,如果首先使用other_type
实例化类模板unique_id
,那么我的程序的先前版本中的任何序列化都将失效。
我已经搜索了这个问题的解决方案,如果唯一值是编译时常量,我找到了几种使用非一致序列化实现它的方法。 如果使用RTTI或类似方法(如boost::sp_typeinfo
,则唯一值显然不是编译时常量,并且存在额外开销。 这个问题的临时解决方案是,以正确的顺序在单独的头中实例化所有unique_id,但这会导致额外的维护和样板代码,这与使用enum unique_id{my_type, other_type};
没有什么不同enum unique_id{my_type, other_type};
。
不幸的是,这个问题的一个很好的解决方案是使用用户定义的文字,据我所知,目前没有编译器支持它们。 语法为'my_type'_id; 'other_type'_id;
'my_type'_id; 'other_type'_id;
与udl的。
我希望有人知道一个技巧,允许在C ++中使用当前标准(C ++ 03 / C ++ 0x)实现可序列化的唯一标识符,如果它适用于最新的稳定MSVC和GNU-G ++,我会很高兴编译器,虽然我希望如果有解决方案,它不可移植。
我想说清楚,使用mpl::set
或类似的结构如mpl::vector
和filtering,并不能解决这个问题,因为元集/向量的范围是有限的,实际上导致的问题不仅仅是预处理器元编程。
@script_name(args)
我向我的一个项目添加了一个构建步骤,这允许我在C ++源文件中编写@script_name(args)
并自动将其替换为相关脚本的输出,例如./script_name.pl args
或./script_name.py args
。
您可能会忽略将语言污染为非标准C ++的想法,但您所要做的就是编写@sha1(my_type)
以获取类名的唯一整数哈希,无论构建顺序如何且无需显式实例。
这只是众多可能的非标准解决方案中的一种,我认为这个解决方案相当简洁。 目前没有很好的方法可以在你的类上强加一个任意的,一致的排序,而不是明确地指定它,所以我建议你简单地放弃并进入显式的实例化路径; 集中信息并没有什么不妥,但正如你所说,它与枚举并没有什么不同,这就是我在这种情况下实际使用的。
持久化数据是一个非常有趣的问题。
我的第一个问题是:你真的想要序列化吗? 如果您愿意调查替代方案,请跳到下一部分。
如果你还在那里,我认为你没有给出所有应得的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库:
很确定你必须实现自己的扩展来实现这一点,我没有看到也没有听说过编译时这样的构造。 MSVC为预处理器提供__COUNTER__
,但我知道没有模板等效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.