唯一综合名称 < >我想用C++中的唯一确定名称生成各种数据类型。例如: struct struct_int_double { int mem0; double mem1; };

唯一综合名称 < >我想用C++中的唯一确定名称生成各种数据类型。例如: struct struct_int_double { int mem0; double mem1; };,c++,compiler-theory,C++,Compiler Theory,目前,我的编译器使用计数器合成名称,这意味着在不同的转换单元中编译相同的数据类型时,名称不一致 以下是不起作用的: 使用ABI mangled_name函数。因为它已经依赖于具有唯一名称的结构。通过假装struct是匿名的,是否可以在符合C++11的ABI中工作 模板例如struct2,因为模板不能与递归类型一起工作 彻底的破坏。因为它给出的名称太长(数百个字符!) 除了全局注册(YUK!)之外,我唯一能想到的就是先创建一个唯一的长名称,然后使用摘要或哈希函数来缩短它(希望没有冲突) 实际问题:

目前,我的编译器使用计数器合成名称,这意味着在不同的转换单元中编译相同的数据类型时,名称不一致

以下是不起作用的:

  • 使用ABI mangled_name函数。因为它已经依赖于具有唯一名称的结构。通过假装struct是匿名的,是否可以在符合C++11的ABI中工作

  • 模板例如struct2,因为模板不能与递归类型一起工作

  • 彻底的破坏。因为它给出的名称太长(数百个字符!)

  • 除了全局注册(YUK!)之外,我唯一能想到的就是先创建一个唯一的长名称,然后使用摘要或哈希函数来缩短它(希望没有冲突)

    实际问题:生成可在类型为匿名的情况下调用的库,例如元组、求和类型、函数类型

    还有其他想法吗

    编辑:添加递归类型问题的描述。考虑定义这样的链表:

    template<class T>
    typedef pair<list<T>*, T> list;
    
    有几个解决办法。对于这个特殊的问题,您可以使用Barton-Nackman技巧的变体,但它不能推广

    有一个一般的解决方案,首先由Gabrielle des Rois展示,使用一个带有递归递归的模板,然后用一个部分专门化来关闭它。但这是极难生成的,即使我能想出如何生成,也可能无法读取

    正确地处理变体也有另一个问题,但这并不是直接相关的(更糟糕的是,对使用可构造类型声明联合的愚蠢限制)


    因此,我的编译器只使用普通的C类型。无论如何,它必须处理多态性:写一个原因是绕过C++模板系统包括模板的问题。这就导致了命名问题。

    我不太理解您的问题

    template<typename T>
    struct SListItem
    {
        SListItem* m_prev;
        SListItem* m_next;
        T m_value;
    };
    
    int main()
    {
        SListItem<int> sListItem;
    }
    
    模板
    结构SListItem
    {
    SListItem*m_prev;
    SListItem*m_下一步;
    T m_值;
    };
    int main()
    {
    SListItem SListItem;
    }
    
    你真的需要这些名字才能同意吗?只需在不同的翻译单元和 RealTytCase< /COD>中分别定义不同的名称,就可以保持C++编译器的快乐。当然,这是可怕的手写代码,但这是由编译器生成的代码,因此您可以(我假设DO)在生成C++代码之前执行必要的静态类型检查。 如果我遗漏了什么,而您确实需要类型名称来表示同意,那么我认为您已经回答了您自己的问题:除非编译器可以在多个翻译单元的翻译之间共享信息(通过一些全局注册表),否则我看不到任何生成唯一,来自类型结构形式的确定性名称,除了明显的名称混乱

    至于名字的长度,我不知道为什么重要?如果您正在考虑使用散列函数来缩短名称,那么很明显,您不需要让人可读,那么为什么它们需要简短呢

    就我个人而言,我可能会生成半人可读的名称,其风格与现有的名称篡改方案类似,而不必使用哈希函数。因此,您可以生成
    sid
    (struct,int,double)或
    si32f64
    (struct,32位整数,64位浮点)或任何内容,而不是生成
    struct\u int\u double
    。这样的名称有一个优点,即它们仍然可以直接解析(这似乎对调试非常重要)

    编辑

    还有一些想法:

    • 模板:我看不出生成模板代码来解决这个问题有什么真正的好处,即使这是可能的。如果您担心链接器中的符号名长度限制,模板帮不了您,因为链接器没有模板概念:它所看到的任何符号都是由C++编译器生成的模板结构的变形形式,并且与FeliX编译器直接生成的冗长名称完全相同。
    • 在FeliX代码中命名的任何类型都应该被保留并直接(或几乎直接)在生成的C++代码中使用。我认为在felix代码中使用的匿名类型的复杂性上存在实际(软)可读性/可维护性约束,这是您需要为其生成名称的唯一约束。我假设您的“变体”是有区别的联合体,因此每个组成部分都必须在felix代码中定义一个名称(标记),并且这些名称也可以保留。(我在评论中提到了这一点,但由于我正在编辑我的答案,我不妨将其包括在内)
    • 减少损坏的名称长度:通过哈希函数运行一个长的损坏名称听起来是最简单的方法,只要使用一个好的哈希函数并在您的哈希名称中保留足够的位,冲突的可能性应该是可以接受的(用于编码散列名称的字母表有37个字符,因此完整的160位sha1散列可以用大约31个字符编写)。散列函数的概念意味着您将无法直接从散列名称返回到原始名称,但您可能永远不需要这样做。我想,您可以在编译过程中转储一个辅助名称映射表(或者从C结构定义中重新生成名称,如果可以的话)。或者,如果您仍然不喜欢散列函数,您可能会定义一个合理紧凑的位级编码(然后将其写入37个字符的标识符字母表),甚至在位级编码上运行一些通用压缩算法。如果你有足够的felix代码进行分析,你甚至可以预先生成一个固定的压缩字典。这就是stark ravi
      template<typename T>
      struct SListItem
      {
          SListItem* m_prev;
          SListItem* m_next;
          T m_value;
      };
      
      int main()
      {
          SListItem<int> sListItem;
      }