为任意UDT';创建可序列化的唯一编译时标识符;s < >我想为任何C++用户定义类型创建唯一的编译时标识符的通用方法。 例如: unique_id<my_type>::value == 0 // true unique_id<other_type>::value == 1 // true unique_id::value==0//true 唯一的\u id::value==1//true

为任意UDT';创建可序列化的唯一编译时标识符;s < >我想为任何C++用户定义类型创建唯一的编译时标识符的通用方法。 例如: unique_id<my_type>::value == 0 // true unique_id<other_type>::value == 1 // true unique_id::value==0//true 唯一的\u id::value==1//true,c++,c-preprocessor,metaprogramming,C++,C Preprocessor,Metaprogramming,我已经使用预处理器元编程实现了类似的东西,问题是,序列化不一致。例如,如果类模板unique\u id首先用other\u type实例化,则我的程序以前版本中的任何序列化都将无效 我已经寻找了这个问题的解决方案,并找到了几种方法,如果唯一值是编译时常量,则可以通过非一致序列化来实现这一点。如果使用RTTI或类似的方法,如boost::sp_typeinfo,那么唯一的值显然不是编译时常量,并且会产生额外的开销。这个问题的一个特别解决方案是,以正确的顺序在一个单独的头中实例化所有的unique_

我已经使用预处理器元编程实现了类似的东西,问题是,序列化不一致。例如,如果类模板
unique\u id
首先用
other\u type
实例化,则我的程序以前版本中的任何序列化都将无效

我已经寻找了这个问题的解决方案,并找到了几种方法,如果唯一值是编译时常量,则可以通过非一致序列化来实现这一点。如果使用RTTI或类似的方法,如
boost::sp_typeinfo
,那么唯一的值显然不是编译时常量,并且会产生额外的开销。这个问题的一个特别解决方案是,以正确的顺序在一个单独的头中实例化所有的unique_id,但这会导致额外的维护和样板代码,这与使用
enum unique_id{my_type,other_type}没有什么不同

解决这个问题的一个好办法是使用用户定义的文本,不幸的是,据我所知,目前没有编译器支持它们。语法应该是
“我的类型”id;'其他“类型”id使用udl

<>我希望有人知道一个技巧,它允许在C++中用当前标准(C++ 03/C++ +0x)实现序列化的唯一标识符,如果它与最新的稳定的MSVC和GNU-G++编译器一起工作,我会很高兴,尽管我希望如果有解决方案,它不是可移植的。
我想明确指出的是,使用
mpl::set
或类似的构造,如
mpl::vector
和过滤,并不能解决这个问题,因为元集/向量的范围有限,实际上会导致比预处理器元编程更多的问题,它允许我在C++源文件中写“代码> @ Script PtEngy(ARGS)< /COD>,并自动替换相关脚本的输出,例如:<代码> /Script PNAM.NP.ARGs<代码> >或代码> ./Script PNAM.NY.ARGs<代码> >p>

你可能会对将语言污染成非标准C++的想法犹豫不决,但你只需编写<代码> @ Sh1(MyObType),以获得类名的唯一整数哈希,而不管生成顺序,而不需要显式实例化。


这只是许多可能的非标准解决方案之一,我认为这是一个相当干净的解决方案。目前,如果不明确地指定类,就无法在类上强加任意的、一致的排序,因此我建议您简单地放弃并采用明确的实例化路线;集中信息并没有什么错,但正如您所说,它与枚举并没有什么不同,枚举是我在这种情况下实际使用的方法。

非常肯定,您必须实现自己的扩展才能实现这一点,我在编译时既没有见过也没有听说过任何这样的构造。MSVC为预处理器提供了
\uuuuu计数器
,但据我所知,没有与之相当的模板。

数据的持久性是一个非常有趣的问题

我的第一个问题是:你真的想要序列化吗?如果你愿意调查一个替代方案,那么跳到下一部分

如果你还在那里,我想你还没有给出
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
}
//静态检测
模板
大小\u t唯一\u id()
{
静态大小\u t const id=some\u散列(typeid(t))//或boost::sp\u typeinfo
返回id;
}
//动态检测
模板
大小\u t唯一\u id(t常量和t)
{
返回一些_散列(typeid(t));//不可能进行回忆录
}
注意:我正在使用本地静态来避免初始化顺序问题,以防在输入
main
之前需要此值

它非常类似于您的
unique_id::value
,即使它是在运行时计算的,也只计算一次,然后将结果(用于静态检测)存储起来以备将来调用

还要注意,它是完全通用的:不需要为每种类型显式地编写函数


这可能看起来很傻,但序列化的问题在于,类型与其表示形式之间存在一对一的映射:

  • 您需要对表示进行版本设置,以便能够解码“较旧”的版本
  • 处理前向兼容性是相当困难的
  • 处理循环引用相当困难(有些框架可以处理)
  • 然后是将信息从一个移动到另一个的问题-->反序列化旧版本会变得混乱和令人沮丧
对于持久保存,我通常建议使用专用BOM表。将保存的数据视为给未来自我的信息。我通常会更进一步,提出一个很棒的Google Proto Buffer库:

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

他已经实现了与之相当的模板,这相当容易做到,而且这和
\uuuu COUNTER\uuuu
都无助于在文件/类之间强加顺序。这是一个有趣的概念,我可能会将其用于我的其他一些代码。这似乎是一个合理的解决方案。在主要编译器中实现udl之前,我将一直使用这种方法。