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()



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM