简体   繁体   English

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

[英]_Generic works with typedef structs or only with primitive types?

Generic o(X) is used to construct Object from several types.泛型o(X)用于从几种类型构造Object But GCC don't expands to typedef types.但是 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 definition of o(x): _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()                  \
                    )

All oNewFrom and oBytes return Object .所有oNewFromoBytes 都返回Object

When vi which type is HashTable aka struct _HashTable * is used with this Generic at line Object ovi = o(vi);vi类型是HashTable aka struct _HashTable *Object ovi = o(vi); gcc call char: oBytes( X, 1), instead HashTable: oNewFrom(HASHTABLE,X), . gcc 调用char: oBytes( X, 1),而不是HashTable: oNewFrom(HASHTABLE,X),

I made any mistake or Generic don't work with structs and typedefs?我犯了任何错误或泛型不适用于结构和类型定义?

Sadly, with _Generic , each expression needs to make compilation sense for the type, not only the one that is used.可悲的是,使用_Generic ,每个表达式都需要对类型进行编译,而不仅仅是使用的那个。

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

HashTable vi; ... o(vi) HashTable vi; ... o(vi) does not compile because oBytes( X, 1) when X is a HashTable does not compile, even though that line is not selected. HashTable vi; ... o(vi)无法编译,因为当XHashTableoBytes( X, 1)无法编译,即使未选择该行也是如此。

With int, void *, double, ... , conversion is defined between the types.使用int, void *, double, ... ,类型之间定义了转换。 Yet with HashTable as a struct , there lacks conversion to/from basic types.然而,使用HashTable作为struct ,缺少与基本类型的转换。


I'd consider posting an alterative, yet OP's post lacks details to embark on that effort.我会考虑发布一个替代方案,但 OP 的帖子缺乏开展这项工作的细节。

A typical alterative passes the address of X to the various functions.一个典型的替代方法是将X的地址传递给各种函数。

Since you have a definition for every type, you could specify the calling convention to be the same for all types.由于您对每种类型都有定义,因此您可以将调用约定指定为对所有类型都相同。

For example:例如:

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

Then your generic macro:然后你的通用宏:

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

Since the argument for the create function is an opaque pointer, the compiler will never complain about what you're passing to the function.由于创建 function 的参数是一个不透明的指针,编译器永远不会抱怨您传递给 function 的内容。 And your function knows how to deal with the data at that address.而您的 function 知道如何处理该地址的数据。

--- Based on your comment --- --- 根据您的评论 ---

Since i don't know exactly what you're trying to accomplish, i only provided the base usage of generics and how to avoid the given warnings.由于我不确切知道您要完成什么,我只提供了 generics 的基本用法以及如何避免给定的警告。

Minimal executable code of what i meant:我的意思的最小可执行代码:

#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;
}

Might (also) be of interest:可能(也)感兴趣:

Generic selection通用选择

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM