_Generic 适用于 typedef 结构还是仅适用于原始类型?

_Generic works with typedef structs or only with primitive types?

泛型 o(X) 用于从多种类型构造 Object。但是 GCC 不会扩展到 typedef 类型。

warning: passing argument 1 of ‘oBytes’ from incompatible pointer type [-Wincompatible-pointer-types]
   68 |    Object ovi = o(vi);
      |                   ^~
      |                   |
      |                   HashTable {aka struct _HashTable *}
../cedata.h:13:43: note: in definition of macro ‘o’
   13 |                     char        : oBytes( X , 1),         \
      |   

_Generic o(x) 的定义:

#define o( X )  _Generic ((X),                            \
                        char        : oBytes( X , 1),         \
                        char *      : oNewFrom(STRING, X),    \
             unsigned   char *      : oNewFrom(STRING, X),    \
                        int         : oNewFrom(INT, X),       \
                        float       : oNewFrom(FLOAT, X),     \
                        short       : oNewFrom(SHORT, X),     \
                        HashTable   : oNewFrom(HASHTABLE,X),  \
                        List        : oNewFrom(LIST, X),      \
                        default     : oNew()                  \
                    )

所有 oNewFromoBytes return Object.

vi 类型 HashTable aka struct _HashTable * 与第 Object ovi = o(vi); 行的此通用一起使用时,gcc 调用 char : oBytes( X , 1), 而不是 HashTable : oNewFrom(HASHTABLE,X), .

我犯了什么错误,或者泛型不适用于结构和类型定义?

由于您对每种类型都有一个定义,因此您可以将调用约定指定为对所有类型都相同。

例如:

create_xxx(void *obj);
//xxx stands for the different types

那么你的通用宏:

#define o(X) _Generic((X), \
    type1: create_type1(X), \
    type2: create_type2(X), \
    ...

由于 create 函数的参数是一个不透明的指针,编译器永远不会抱怨您传递给该函数的内容。并且您的函数知道如何处理该地址处的数据。

--- 根据您的评论 ---

由于我不确切知道你想要完成什么,我只提供了泛型的基本用法以及如何避免给定的警告。

我的意思的最小可执行代码:

#include <stdlib.h>
#include <stdio.h>

typedef struct ObjectRec {
    int id;
} Object;

void* create_int(void *ptr)
{
    printf("create_int\n");
    return ptr;
}

void* create_float(void *ptr)
{
    printf("create_float\n");
    return ptr;
}

void* create_obj(void *ptr)
{
    printf("create_obj\n");
    ((Object*) ptr)->id = 0;
    return ptr;
}

#define o(X) _Generic((X), \
    int*: create_int, \
    float*: create_float, \
    Object*: create_obj \
)(X)

int main()
{
    int i = 1;
    float f = 0.5f;
    Object obj;

    o(&i);
    o(&f);
    o(&obj);

    return EXIT_SUCCESS;
}

可能(也)感兴趣:

Generic selection

遗憾的是,对于 _Generic,每个表达式都需要对类型具有编译意义,而不仅仅是使用的那个。

#define o( X )  _Generic ((X),                            \
                    char        : oBytes( X , 1),         \
                    ...
                    HashTable   : oNewFrom(HASHTABLE,X),  \
                    ...
                )

HashTable vi; ... o(vi) 不编译,因为 oBytes( X , 1)XHashTable 时不编译,即使没有选择该行。

使用int, void *, double, ...,类型之间的转换被定义。然而 HashTable 作为 struct,缺少转换 to/from 基本类型。


我会考虑 post 替代方案,但 OP 的 post 缺乏开始这项工作的详细信息。

典型的替代方法是将 X 的地址传递给各种函数。