_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() \
)
所有 oNewFrom 和 oBytes 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
,每个表达式都需要对类型具有编译意义,而不仅仅是使用的那个。
#define o( X ) _Generic ((X), \
char : oBytes( X , 1), \
...
HashTable : oNewFrom(HASHTABLE,X), \
...
)
HashTable vi; ... o(vi)
不编译,因为 oBytes( X , 1)
当 X
是 HashTable
时不编译,即使没有选择该行。
使用int, void *, double, ...
,类型之间的转换被定义。然而 HashTable
作为 struct
,缺少转换 to/from 基本类型。
我会考虑 post 替代方案,但 OP 的 post 缺乏开始这项工作的详细信息。
典型的替代方法是将 X
的地址传递给各种函数。
泛型 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() \
)
所有 oNewFrom 和 oBytes 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
,每个表达式都需要对类型具有编译意义,而不仅仅是使用的那个。
#define o( X ) _Generic ((X), \
char : oBytes( X , 1), \
...
HashTable : oNewFrom(HASHTABLE,X), \
...
)
HashTable vi; ... o(vi)
不编译,因为 oBytes( X , 1)
当 X
是 HashTable
时不编译,即使没有选择该行。
使用int, void *, double, ...
,类型之间的转换被定义。然而 HashTable
作为 struct
,缺少转换 to/from 基本类型。
我会考虑 post 替代方案,但 OP 的 post 缺乏开始这项工作的详细信息。
典型的替代方法是将 X
的地址传递给各种函数。