• C 语言中模板的几种实现方式


    简单宏定义实现

    简单宏定义 - 方式一

    这种方式将主要实现部分放在一个宏定义中,利用字符替换的方式实现不同 type 的运算,详细思路见代码:

    simple_macro_1.c

    #include <stdint.h>
    
    #define INT8 8
    #define INT16 16
    #define INT32 32
    
    #define DO_MAIN(type) do {                      
            int i;                                  
            type *p = buf;                          
                                                    
            for (i = 0; i < len; i++) {             
                    p[i] *= k;                      
            }                                       
    } while(0)
    
    void func(void *buf, int len, float k, int request)
    {
            if (request == INT8) {
                    DO_MAIN(int8_t);
            } else if (request == INT16) {
                    DO_MAIN(int16_t);
            } else if (request == INT32) {
                    DO_MAIN(int32_t);
            }
    }
    

    简单宏定义 - 方式二

    这种方式直接利用宏定义实现几个同类函数的定义,详见代码:

    simple_macro_2.c

    #define DECLARE_FUNC(n)                                 
    static void func_##n(int##n##_t *p, int len, float k)   
    {                                                       
        int i;                                              
                                                            
        for (i = 0; i < len; i++)                           
            p[i] *= k;                                      
    }
    
    DECLARE_FUNC(8)
    DECLARE_FUNC(16)
    DECLARE_FUNC(32)
    

    接下来就可以使用 func_8()func_16()func_32() 三个函数了。

    包装函数实现

    这种方式理解起来非常简单,就是简单地利用一个函数将多个同类函数进行统一整合,详见代码:

    alternative_function_creator.c

    /*************************************
    * foo(), bar(), baz() 三个函数为已有函数
    **************************************/
    
    static inline int process_image(void *img, int width, int height, const int n)
    {
        int x, y;
    
        for (y = 0; y < height; y++) {
            for (x = 0; x < width; x++) {
                if      (n == 0) foo(img, x, y);
                else if (n == 1) bar(img, x, y);
                else             baz(img, x, y);
            }
        }
    }
    
    int process_image_foo(void *img, int width, int height)
    {
        return process_image(img, width, height, 0);
    }
    
    int process_image_bar(void *img, int width, int height)
    {
        return process_image(img, width, height, 1);
    }
    
    int process_image_baz(void *img, int width, int height)
    {
        return process_image(img, width, height, 2);
    }
    

    宏定义和包装函数混合使用实现

    针对上述方式,process_image_fooprocess_image_barprocess_image_baz 三个函数可以利用宏定义简化书写,如下:

    mix_macros_functions.c

    static inline int process_image(void *img, int width, int height, const int n)
    {
        int x, y;
    
        for (y = 0; y < height; y++) {
            for (x = 0; x < width; x++) {
                if      (n == 0) foo(img, x, y);
                else if (n == 1) bar(img, x, y);
                else             baz(img, x, y);
            }
        }
    }
    
    #define DECLARE_PROCESS_IMAGE_FUNC(name, n)                 
    int process_image_##name(void *img, int width, int height)  
    {                                                           
        return process_image(img, width, height, n);            
    }
    
    DECLARE_PROCESS_IMAGE_FUNC(foo, 0)
    DECLARE_PROCESS_IMAGE_FUNC(bar, 1)
    DECLARE_PROCESS_IMAGE_FUNC(baz, 2)
    

    这样就可以实现上一种方式同样的效果

    外部文件实现

    我们还可以用单独的源文件和头文件来实现模板函数,像这样:

    extermal_file.c

    #if defined(TEMPLATE_U16)
    
    #    define RENAME(N)   N ## _u16
    #    define TYPE        uint16_t
    #    define SUM_TYPE    uint32_t
    
    #elif defined(TEMPLATE_U32)
    
    #    define RENAME(N)   N ## _u32
    #    define TYPE        uint32_t
    #    define SUM_TYPE    uint64_t
    
    #elif defined(TEMPLATE_FLT)
    
    #    define RENAME(N)   N ## _flt
    #    define TYPE        float
    #    define SUM_TYPE    float
    
    #elif defined(TEMPLATE_DBL)
    
    #    define RENAME(N)   N ## _dbl
    #    define TYPE        double
    #    define SUM_TYPE    double
    
    #endif
    
    TYPE RENAME(func)(const TYPE *p, int n)
    {
        int i;
        SUM_TYPE sum = 0;
    
        for (i = 0; i < 1<<n; i++)
            sum += p[i];
        return sum;
    }
    
    #undef RENAME
    #undef TYPE
    #undef SUM_TYPE
    

    可以像下面这样使用模板函数:

    mian.c

    #include <stdint.h>
    
    #define TEMPLATE_U16
    #include "evil_template.c"
    #undef TEMPLATE_U16
    
    #define TEMPLATE_U32
    #include "evil_template.c"
    #undef TEMPLATE_U32
    
    #define TEMPLATE_FLT
    #include "evil_template.c"
    #undef TEMPLATE_FLT
    
    #define TEMPLATE_DBL
    #include "evil_template.c"
    #undef TEMPLATE_DBL
    

    只需要在使用前对相应类型进行宏定义即可,对应的函数分别是 func_u16()func_u32()func_flt()func_dbl()


  • 相关阅读:
    [Vue] Create Filters in Vue.js
    [Vue] Import component into page
    [Angular Form] ngModel and ngModelChange
    [Ramda] Convert a QueryString to an Object using Function Composition in Ramda
    [Vue] Use basic event handling in Vue
    [Ramda] Declaratively Map Data Transformations to Object Properties Using Ramda evolve
    Linux2.6内核--VFS层中和进程相关的数据结构
    [置顶] Firefox OS 学习——Gaia 编译分析
    ORACLE 索引概述
    【笔试&面试】C#的托管代码与非托管代码
  • 原文地址:https://www.cnblogs.com/dawn-l/p/6725868.html
Copyright © 2020-2023  润新知