繁体   English   中英

为任意UDT创建可序列化的唯一编译时标识符

[英]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库:

  • 向后兼容向前兼容
  • 几种格式输出 - >人类可读(用于调试)或二进制
  • 几种语言可以读/写相同的消息(C ++,Java,Python)

很确定你必须实现自己的扩展来实现这一点,我没有看到也没有听说过编译时这样的构造。 MSVC为预处理器提供__COUNTER__ ,但我知道没有模板等效。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM