C base _Generic generic application

Introduction - _Generic Usage Profile

#include <stdio.h>

#define TYPENAME_CASE(type)                         \
    type: #type,

#define TYPENAME_POINTER_CASE(type)                 \
    TYPENAME_CASE(type)                             \
    TYPENAME_CASE(type *)                           \

#define TYPENAME_UNSIGNED_CASE(type)                \
    TYPENAME_POINTER_CASE(type)                     \
    TYPENAME_POINTER_CASE(unsigned type)            \

#define TYPENAME(x) _Generic((x),                   \
    TYPENAME_POINTER_CASE(_Bool)                    \
    TYPENAME_UNSIGNED_CASE(char)                    \
    TYPENAME_UNSIGNED_CASE(short)                   \
    TYPENAME_UNSIGNED_CASE(long)                    \
    TYPENAME_UNSIGNED_CASE(long long)               \
    TYPENAME_POINTER_CASE(float)                    \
    TYPENAME_POINTER_CASE(double)                   \
    TYPENAME_POINTER_CASE(long double)              \
    TYPENAME_POINTER_CASE(float _Complex)           \
    TYPENAME_POINTER_CASE(double _Complex)          \
    TYPENAME_CASE(void *)                           \
    default: "other"                                \
)

int main(int argc, char * argv[]) {
    double _Complex c;
    double _Complex * p = &c;

    puts(TYPENAME(p));

    return 0;
}

 

 

Text - _Generic achieve function overloading

#include <stdio.h>

void foo_void(void) {
    printf("void\n");
}

void foo_int(int c) {
    printf("int: %d\n", c);
}

void foo_char(char c) {
    printf("char: %c\n", c);
}

void foo_double(double c) {
    printf("double: %f\n", c);
}

void foo_double_int(double c, int d) {
    printf("double: %f, int: %d\n", c, d);
}

#define foo(...)                                            \
SELECT(__VA_ARGS__)(__VA_ARGS__)

#define CONCAT(X, Y) CONCAT_(X, Y)
#define CONCAT_(X, Y) X ## Y

#define SELECT(...)                                         \
CONCAT(SELECT_, NARG(__VA_ARGS__))(__VA_ARGS__)

#define SELECT_0()                                          \
foo_void

#define SELECT_1(_1) _Generic((_1),                         \
    int: foo_int,                                           \
    char: foo_char,                                         \
    double: foo_double                                      \
)

#define SELECT_2(_1, _2) _Generic((_1),                     \
    double: _Generic((_2),                                  \
        int: foo_double_int                                 \
    )                                                       \
)

#define ARGN(...) ARGN_(__VA_ARGS__)
#define ARGN_(_0, _1, _2, /*...*/ N, ...) N

#define NARG(...)                                           \
ARGN(__VA_ARGS__ COMMA(__VA_ARGS__) 3, 2, 1 , 0 )
 #define HAS_COMMA (...) \ 
ARGN (__ VA_ARGS__, 1 , 1 , 0 ) 

#define SET_COMMA (...), #define PARAGRAPH (...) SELECT_COMMA (\ 
    HAS_COMMA (__ VA_ARGS__), \ 
    HAS_COMMA (__VA_ARGS__ ()), \ 
    HAS_COMMA (SET_COMMA __VA_ARGS__), \ 
    HAS_COMMA (SET_COMMA __VA_ARGS__ ()) \ 
) #define SELECT_COMMA (_0, _1, _2, _3) \ 
SELECT_COMMA _ (_ 0, _1, _2, _3)




#define SELECT_COMMA_(_0, _1, _2, _3)                       \
COMMA_ ## _0 ## _1 ## _2 ## _3

#define COMMA_0000 ,
#define COMMA_0001
#define COMMA_0010 ,
#define COMMA_0011 ,
#define COMMA_0100 ,
#define COMMA_0101 ,
#define COMMA_0110 ,
#define COMMA_0111 ,
#define COMMA_1000 ,
#define COMMA_1001 ,
#define COMMA_1010 ,
#define COMMA_1011 ,
#define COMMA_1100 ,
#define COMMA_1101 ,
#define COMMA_1110 ,
#define COMMA_1111 ,

int main(int argc, char** argv)
{
    foo();
    foo(7);
    foo(10.12);
    foo(12.10, 7);
    foo((char)'s');

    return 0;
} 

{

         Code context may be discussed below in detail with reference 1 and 2. ~ Thought master thinking 

  1. https://stackoverflow.com/questions/479207/how-to-achieve-function-overloading-in-c?rq=1

  2. https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/

}

For COMMA macro above put.c demonstration, we use some demo below (define.c) to simple dismantling part of the idea

#include <stdio.h>

// https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/

#define _ARG16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, ...) _16
#define HAS_COMMA(...) _ARG16(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)

//
// _TRIGGER_PARENTHESIS_ __VA_ARGS__ (/* empty */)
//
#define _TRIGGER_PARENTHESIS_(...) ,

#define HAS_COMMA_EMPTY(...) HAS_COMMA(_TRIGGER_PARENTHESIS_ __VA_ARGS__(/* empty */))

int main(int argc, char * argv[]) {
    printf("%d\n", HAS_COMMA());
    printf("%d\n", HAS_COMMA(1));
    printf("%d\n", HAS_COMMA(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15));
    printf("%d\n", HAS_COMMA(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16));
    printf("%d\n", HAS_COMMA(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17));

    printf("%d\n", HAS_COMMA(,));
    printf("%d\n", HAS_COMMA_EMPTY());
    return 0;
}

 

细细品味推荐的链接. 专业没那么简单 ~ 

 

后记 - 简单并不简单

  下次再见, 有问题欢迎沟通交流指正 ~ 祝好运 

  音乐 : 约在春天相见 

Guess you like

Origin www.cnblogs.com/life2refuel/p/12330462.html