zoukankan      html  css  js  c++  java
  • C 基础 _Generic 泛型应用

    引言 - _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;
    }

     

    { warning 点睛呀, GCC 亲自指出自己的 BUG} 

    正文 - _Generic 实现函数重载

    #include <stdio.h>
    
    void foo_void(void) {
        printf("void
    ");
    }
    
    void foo_int(int c) {
        printf("int: %d
    ", c);
    }
    
    void foo_char(char c) {
        printf("char: %c
    ", c);
    }
    
    void foo_double(double c) {
        printf("double: %f
    ", c);
    }
    
    void foo_double_int(double c, int d) {
        printf("double: %f, int: %d
    ", 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
    ", HAS_COMMA());
        printf("%d
    ", HAS_COMMA(1));
        printf("%d
    ", HAS_COMMA(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15));
        printf("%d
    ", HAS_COMMA(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16));
        printf("%d
    ", HAS_COMMA(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17));
    
        printf("%d
    ", HAS_COMMA(,));
        printf("%d
    ", HAS_COMMA_EMPTY());
        return 0;
    }

     

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

    后记 - 简单并不简单

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

      音乐 : 约在春天相见 

  • 相关阅读:
    Do You See Me? Ethical Considerations of the Homeless
    ELDER HOMELESSNESS WHY IS THIS AN ISSUE?
    Endoflife support is lacking for homeless people
    html内联框架
    html字体
    html块 div span
    html列表
    html表格
    SQL Server管理员专用连接的使用   作为一名DBA,经常会处理一些比较棘手的服务无响应问题,鉴于事态的严重性,多数DBA可能直接用“重启”大法,以便尽快的恢复生产环境的正常运转,但是多数情况
    如何配置最大工作线程数 (SQL Server Management Studio)
  • 原文地址:https://www.cnblogs.com/life2refuel/p/12330462.html
Copyright © 2011-2022 走看看