用C语言实现模板类的一些个人思路

用C语言实现模板类的一些个人思路

0. FAQ

  • Q: 为什么要用模板?
  • A: 为了解决函数重载问题。例如,在C++中,我们要比较两个int型变量的哪个大,并返回其中较大的值,可能会写这样的函数:
int Max(int a, int b) { return a > b ? a : b; }
int main() {
    printf("%d\n", Max(123, 456));
    return 0;
}

但是,如果我们还要比较更多的类型,例如char型,double型之类的,我们都需要重新写一个类似的实现,这很不方便:

char Max(char a, char b) { return a > b ? a : b; }
double Max(double a, double b) { return a > b ? a : b; }
int main() {
    printf("%c, %lf\n", Max('a', 'z'), Max(1.1, 2.2));
    return 0;
}

这个时候我们可以考虑使用模板来简化代码:

template <typename T>
T Max(T a, T b) { return a > b ? a : b; }
int main() {
    printf("%d, %c, %lf\n", Max(123, 456), Max('a', 'z'), Max(1.1, 2.2)); 
    return 0;
}

  • Q: C能重载?
  • A: 不能,C只能像这样子:
int Max_int(int a, int b) { return a > b ? a : b; }
char Max_char(char a, char b) { return a > b ? a : b; }
double Max_double(double a, double b) { return a > b ? a : b; }
int main() {
    printf("%d, %c, %lf\n", Max_int(123, 456), Max_char('a', 'z'), Max_double(1.1, 2.2));
    return 0;
}

  • Q: 道理我都懂,有C++了,为什么还要用C实现模板?
  • A: 虽然一般情况下都能直接写C++来代替C程序啦,不过确实存在无法使用C++的场合。很不幸,我工作所用的语言只能是C,于是,之前用惯了C++的我决定探索一下如何用C实现模板- -+

1. 目前个人写法风格

1.0 模板函数

首先,用前面的Max函数为例,先看一下我目前的写法风格吧:-P

需要注意的是:为防止宏嵌套出错,例如_Max(Pair(int, char))会被拓展成Max$_Pair(int, char)_$这样的不合法变量名(Pair的定义见1.1模板类示例),我们都需要多写一个类似于#define Max(T) _Max(T)这样的操作

#define _Max(T) Max$_##T##_$
#define Max(T) _Max(T)

#define _Max_IMPL(T) T Max(T)(T a, T b) { return a > b ? a : b; }
#define Max_IMPL(T) _Max_IMPL(T)

Max_IMPL(int);
Max_IMPL(char);
Max_IMPL(double);

int main() {
    printf("%d, %c, %lf\n", Max(int)(123, 456), Max(char)('a', 'z'), Max(double)(1.1, 2.2));
    return 0;
}

下面解释一下上面的代码到底做了什么:

  • 用宏来模仿C++的写法 —— #define _Max(T) Max$_##T##_$
    这里用了Max(T)宏来模仿C++的Max<T>写法。

    例如:Max(int),宏拓展后实际上等于Max$_int_$$符号确实是合法变量名),这里用$_表示C++中模板的尖括号左侧<,用_$表示尖括号右侧>

  • 模板实现 —— #define _Max_IMPL(T) T Max(T a, T b) { return a > b ? a : b; }
    相当于C++的template <typename T> T Max(T a, T b) { return a > b ? a : b; }

  • 实例化模板 —— Max_IMPL(int);
    由于C不是C++,所以需要使用者自己去实例化对应的模板类型,此处宏拓展出来的代码为int Max(int)(int a, int b) { return a > b ? a : b; },然后Max(int)再拓展为Max$_int_$,于是最终结果为:
    int Max$_int_$(int a, int b) { return a > b ? a : b; }

  • 使用 —— Max(int)(123, 456)
    相当于C++的Max<int>(123, 456)

像这样,我们就实现了一个T Max<T>(T, T)模板函数了!在此基础上,我们可以更进一步:如果能做一个检测代码中Max使用了哪些模板类型,然后在编译前自动添加实现Max_IMPL(…)完成“实例化”的程序,就可以完成类似于C++的模板类型推断功能了- -+


1.1 模板类

模板类同理,我们以简单的Pair为例(保存两个类型数据的结构)

#define _Pair(T1, T2) Pair$_##T1##_$$_##T2##_$
#define Pair(T1, T2) _Pair(T1, T2)

#define _Pair_IMPL(T1, T2) typedef struct { T1 t1; T2 t2; } Pair(T1, T2)
#define Pair_IMPL(T1, T2) _Pair_DEF(T1, T2)

Pair_IMPL(int, char);
Pair_IMPL(int, double);

int main() {
    Pair(int, char) p_ic;
    Pair(int, double) p_id;
    p_ic.t1 = 123;
    p_ic.t2 = 'a';
    p_id.t1 = 456;
    p_id.t2 = 1.1;
    return 0;
}
  • #define _Pair(T1, T2) Pair$_##T1##_$$_##T2##_$
    Pair(T1, T2)模仿C++中Pair<T1, T2>的写法
  • #define _Pair_IMPL(T1, T2) typedef struct Pair(T1, T2) { T1 t1; T2 t2; } Pair(T1, T2)
    相当于template<typename T1, typename T2> struct Pair{ T1 t1; T2 t2; }
  • Pair_IMPL(int, char);
    实例化Pair<int, char>,此处宏拓展的最终结果为:
    typedef struct { int t1; char t2; } Pair$_int_$$_char_$
  • Pair(int, char) p_ic;
    相当于Pair<int, char> p_ic;

像这样,我们就完成了简单的Pair<T1, T2>模板类了


个人项目(完善中):https://github.com/NumbFish-Luo/NfLib
参考资料:C语言宏高级用法 https://www.cnblogs.com/alantu2018/p/8465911.html

  • 12
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值