码迷,mamicode.com
首页 > 其他好文 > 详细

C 基础 _Generic 泛型应用

时间:2020-02-19 12:56:27      阅读:103      评论:0      收藏:0      [点我收藏+]

标签:case   ext   沟通   parent   https   简介   UNC   ons   mic   

引言 - _Generic 用法简介

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

 技术图片

 

正文 - _Generic 实现函数重载

#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 COMMA(...) 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;
} 

技术图片

{

         代码脉络可以详细参照下面 1和 2 讨论.  思索大师的思维 ~ 

  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/

}

对于上面 put.c 演示的 COMMA 宏, 我们用下面一段 demo (define.c)来简单拆解其中一部分思路

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

技术图片 

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

 

后记 - 简单并不简单

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

  音乐 : 约在春天相见 

C 基础 _Generic 泛型应用

标签:case   ext   沟通   parent   https   简介   UNC   ons   mic   

原文地址:https://www.cnblogs.com/life2refuel/p/12330462.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!