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

时间:2021-11-24 04:55:59

简单宏定义实现

简单宏定义 - 方式一

这种方式将主要实现部分放在一个宏定义中,利用字符替换的方式实现不同 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()