BLOG

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

简单宏定义实现

简单宏定义 - 方式一

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

simple_macro_1.c

#include

#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_foo、process_image_bar 和 process_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<

sum += p[i];

return sum;

}

#undef RENAME

#undef TYPE

#undef SUM_TYPE

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

mian.c

#include

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

参考文献:http://blog.pkh.me/p/20-templating-in-c.html *