C++ - 什么是 "type transparent class"?

标签 c++ gcc

使用gcc编译一个包含十进制数据类型支持的程序,最近遇到如下错误:

error: type transparent class 'std::decimal::decimal32' has base classes

快速浏览一下 GCC 的源代码树,发现此错误消息位于 gcc/cp/class.c 中。

什么是“类型透明类”?为什么这样的类有“基类”是错误的?

最佳答案

semantics.c 中阅读更多 GCC 的源代码:

  if (TREE_CODE (t) == RECORD_TYPE
      && !processing_template_decl)
    {
      tree ns = TYPE_CONTEXT (t);
      if (ns && TREE_CODE (ns) == NAMESPACE_DECL
          && DECL_CONTEXT (ns) == std_node
          && DECL_NAME (ns)
          && !strcmp (IDENTIFIER_POINTER (DECL_NAME (ns)), "decimal"))
        {
          const char *n = TYPE_NAME_STRING (t);
          if ((strcmp (n, "decimal32") == 0)
              || (strcmp (n, "decimal64") == 0)
              || (strcmp (n, "decimal128") == 0))
            TYPE_TRANSPARENT_AGGR (t) = 1;
        }
    }

此代码表示在以下情况下将类型标记为透明:

  • 它是一个结构体,但不是一个模板;
  • 它在命名空间级别,并且该命名空间是 std::decimal
  • 并命名为decimal32decimal64decimal128

class.c中有你遇到的错误检查,还有一些。

mangle.c中:

      /* According to the C++ ABI, some library classes are passed the
         same as the scalar type of their single member and use the same
         mangling.  */
      if (TREE_CODE (type) == RECORD_TYPE && TYPE_TRANSPARENT_AGGR (type))
        type = TREE_TYPE (first_field (type));

评论是这里的关键。我认为这意味着将透明类型替换为其第一个(也是唯一一个)成员的类型,因此它可以在第一个成员可以使用的任何地方使用。例如,在我的 include/decimal 类中 std::decimal::decimal32 有一个类型为 __decfloat32 的字段(来自之前的 typedef float __decfloat32 __attribute__((mode(SD)));),因此任何采用 __decfloat32 的函数都可以采用 std::decimal::decimal32,反之亦然。甚至功能装饰也是如此。这个想法可能是让这个类 ABI 与 C 类型 _Decimal32_Decimal64_Decimal128 兼容。

现在,您如何获得带有基类的 class decimal32?我唯一的猜测是您包含不兼容(可能较旧)的头文件,具有完全不同的实现。

更新

经过一番调查,看来我对 ABI 和函数修饰的猜测是正确的。以下代码:

#include <decimal/decimal>
using namespace std::decimal;

 //This is a synonym of C99 _Decimal32, but that is not directly available in C++
typedef float Decimal32 __attribute__((mode(SD)));

void foo(decimal32 a) {}
void foo(Decimal32 a) {}

给出奇怪的错误:

/tmp/ccr61gna.s: Assembler messages:
/tmp/ccr61gna.s:1291: Error: symbol `_Z3fooDf' is already defined

也就是说,编译器前端认为重载没有问题并发出 asm 代码,但由于两个函数的修饰相同,因此汇编器失败。

现在,正如 Ben Voigt 在评论中所建议的那样,这是否与 GCC 不符?我不知道......你应该能够用你想要的任何两种不同类型编写重载函数。但是OTOH,不使用一些编译器扩展是不可能得到Decimal32类型的,所以这种类型的含义是实现定义的......

关于C++ - 什么是 "type transparent class"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17709264/

相关文章:

c++ - 如何在 QString 中检测到非 ASCII 字符?

c++ - 在 QtCreator 中添加静态 .a 库

c++ - 如何使用 if...else 语句从一组随机生成的数字中提取特定数字?

C++,在多行代码中注释

mysql - 使用gcc的C代码无法链接到mysql头?

c - 当我们在c中使用fork时,进程之间是否共享数据?

c# - 如何为我的坐标系获取 "thinner"图?

c++ - 寻找 XXYY 形式的所有完美正方形

c - 用于模块化 C 应用程序的资源

c++ - 无法使用 GCC 编译器 4.7.3 在 AIX 上编译具有线程支持的 C++ 程序