C 基础 _Generic 泛型应用

Posted life2refuel

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}

 技术图片

 

正文 - _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;
}

技术图片 

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

 

后记 - 简单并不简单

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

  音乐 : 约在春天相见 

以上是关于C 基础 _Generic 泛型应用的主要内容,如果未能解决你的问题,请参考以下文章

[Unity] C#中级编程 - 04 - 泛型/构造函数/ref

这个嵌套类构造函数片段可以应用于泛型类吗?

C#--泛型(Generic)

Java基础之Comparable接口, Collections类,Iterator接口,泛型(Generic)

Java基础加强总结——泛型

学习笔记Java基础知识——泛型与集合