c语言 利用宏实现函数重载
·
前言
众所周知c语言不支持重载,虽然重载给编写代码还是带来了不少的便利性。如果想要在c语言中实现重载,那就需要一些特殊的手段了,比如说使用宏。本文讲述的方法是,网上已经存在,笔者经过实践调整实现以兼容不同编译器。
一、如何实现?
基本原理是通过宏的参数的个数,定位到对应参数个数的函数,所以只能通过参数个数区分重载。
1、基础宏
#if defined(_MSC_VER)
#define _AC_OVERLOAD_T(t) t
#define _AC_OVERLOAD_N(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, N, ...) N
#define AC_OVERLOAD(...) _AC_OVERLOAD_T(_AC_OVERLOAD_N(__VA_ARGS__))
#else
#define _AC_OVERLOAD_T(...) _AC_OVERLOAD_N(__VA_ARGS__, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define _AC_OVERLOAD_N(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, N, ...) N
#define _AC_CAT(a, b) a##b
#define AC_CAT(a, b) _AC_CAT(a, b)
#define _AC_OVERLOAD(func, N) AC_CAT(func##_, N)
#define AC_OVERLOAD(func, ...) _AC_OVERLOAD(func, _AC_OVERLOAD_T(__VA_ARGS__))(__VA_ARGS__)
#endif
2、定义函数
//规则是名称+_数字(参数个数)
// 函数一
void add_1(int a)
{
printf("call add1 \n");
}
// 函数二
void add_2(int *array, int len)
{
printf("call add2 \n");
}
3、定义重载宏
当前版本,CL和其他编译器不同,所以需要定义两套重载宏函数。
#if defined(_MSC_VER)
// CL相对麻烦一些,需要在AC_OVERLOAD相应位置替换为对应参数个数的函数
#define add(...) AC_OVERLOAD(__VA_ARGS__, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, add_2(__VA_ARGS__), add_1(__VA_ARGS__), 0)
#else
// gcc的较清晰明了:拼接规则是函数名称+_数字(参数个数)。
// add(...) 为调用的名称可以自定义。AC_OVERLOAD中的add为上面定义的函数不带_数字的部分。
#define add(...) AC_OVERLOAD(add, __VA_ARGS__)
#endif
4、调用
add(1);
int array[]={0,1};
add(array,2);
二、完整示例
代码如下(示例):
#include <stdio.h>
//基础宏 通用的
#if defined(_MSC_VER)
#define _AC_OVERLOAD_T(t) t
#define _AC_OVERLOAD_N(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, N, ...) N
#define AC_OVERLOAD(...) _AC_OVERLOAD_T(_AC_OVERLOAD_N(__VA_ARGS__))
#else
#define _AC_OVERLOAD_T(...) _AC_OVERLOAD_N(__VA_ARGS__, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define _AC_OVERLOAD_N(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, N, ...) N
#define _AC_CAT(a, b) a##b
#define AC_CAT(a, b) _AC_CAT(a, b)
#define _AC_OVERLOAD(func, N) AC_CAT(func##_, N)
#define AC_OVERLOAD(func, ...) _AC_OVERLOAD(func, _AC_OVERLOAD_T(__VA_ARGS__))(__VA_ARGS__)
#endif
//当前需要重载方法的宏
#if defined(_MSC_VER)
// CL相对麻烦一些,需要在AC_OVERLOAD相应位置替换为宏
#define add(...) AC_OVERLOAD(__VA_ARGS__, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, add_2(__VA_ARGS__), add_1(__VA_ARGS__), 0)
#else
// gcc的较清晰明了:拼接规则是函数名称+_数字(参数个数)。
// add(...) 为调用的名称可以自定义。AC_OVERLOAD中的add为上面定义的函数不带_数字的部分。
#define add(...) AC_OVERLOAD(add, __VA_ARGS__)
#endif
//具体重载的函数,规则是名称+_数字(参数个数)
// 函数一
void add_1(int a)
{
printf("call add1 \n");
}
// 函数二
void add_2(int *array, int len)
{
printf("call add2 \n");
}
//调用
int main()
{
add(1);
int array[] = {0, 1};
add(array, 2);
return 0;
}
效果预览:
总结
以上就是今天要讲的内容,当前的实现不同编译器略有差异,所以使用起来略微麻烦一些,但是总的来说也是稳定实现了简单的函数重载,具有一定的实用性,后面可能会研究下CL的宏能否进一步优化。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)