Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
470 views
in Technique[技术] by (71.8m points)

c - _Generic works with typedef structs or only with primitive types?

Generic o(X) is used to construct Object from several types. But GCC don't expands to typedef types.

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):

#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.

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

I made any mistake or Generic don't work with structs and typedefs?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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. And your function knows how to deal with the data at that address.

--- 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.

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
");
    return ptr;
}

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

void* create_obj(void *ptr)
{
    printf("create_obj
");
    ((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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...