C1X系列:type-generic macros

 

C1X系列:type-generic macros

 

by 林海枫

http://blog.csdn.net/linyt/archive/2010/10/25/5966485.aspx


承蒙转载,请保持本文的完整性,请匆用于商业用途。


type-generic macros在新的C1X草案又称为Generic selection,根据它的提案和最新C1X草案,可将type-generic macros翻译成泛型宏或者通用类型宏。 type-generic macros是一种编译期技术,它允许开发人员根据宏的某个参数的类型来确定生成的内容。这与C++中的函数重载有点类似,但又有不同。

type-generic macros并不是 C1X提出的概念,早在C99时就有了,只不过当时没有对它进行标准化。 C99中引用了头文件<tgmath.h>,给开发人员提供大量初等数学数函接口。

在C99中,程序员可以以不同的类型来调用 sin函数, 比如:

sin(1), 实际上调用sin(1.0)

sin(1.0F), 实际上调用sinf(1.0F)

sin(1.0L),实际上调用sinl(1.0L)

实际上,sin这个接口是一个宏,它会用户传递的实际类型来决定最终调用的函数。 sin就是一个type-generic macro。

1. type-generic macros的技术现状

为了实现C99中tgmath.h中的接口,各个编译器八仙过海,各显神通。

 

Edison Design Group(EDG)为实现tgmath.h提出了一种编译魔法,让开发人员(库的开发者)使用__generic可轻松实现tgmath.h的接口。如上述的sin接口可定义如下:

#define sin(x) __generic(x,,, sin, sinf, sinl, csin, csinf, csinl)(x)

__generic就是EDG的把戏,它并不生成生代码,只在编译期,根据x的类型float, double, long double, float complex, double complex或long double complex来选择后面对应的6个函数。

当然EDG的__generic用来实现C1X的type-generic macros是不行的,它只能识别浮点数和复数一共6种类型,并且__generic后的六种函数必须按这种顺序来排列, 但对C99标准中的generic function,这种技术已足够了。

 

gnu GCC算得上是一个体贴入微的编译器,它在不违背标准和C语义的情况下,提供很多编译时的内置小工具,让你编写功能强太,可以控制更底层的代码。当然,这些feature只能在gcc上使用。

C99中的sin在gcc可以蝉联__builtin_choose_expr,__builtin_types_compatible_p和typeof来实现。

__builtin_types_compatible_p (typeof (x), long double) 在编译期判断x的基础类型是否为long double(即除去const, volatile
等修饰符后的类型), 而__builtin_choose_expr 是编译期的三元组运算符,如果条件为true,则运算第一个表达式,否则运算第二个




表达式。gcc编译器的tgmath.h实现,并没有使用上述的__builtin_技术,而是使用一些sizeof, typeof和其它__builtin_,但可读性非常差。

C1X之type-generic macros

目前type-generic macros有两个提案,分别是N1340 Extensible Generic Math FunctionsN1404 General support for type-generic macros. N1340从C99的tgmath实现谈起,提出将EDG的实现方案进行标准化,以解开发人员编写可移植的泛型宏之苦。N1404在N1340的基础上,对type-generic macros的语法形式方面进行改进,现已成形于最新的C1X草案中。

C1X中引入了新关键字_Generic来实现type-generic macros, 这就一个语法糖魔术,它根据第一个参数的类型,和后面的类型-表达式关联来实现编译期的替换。它的语法格式规定如下:


利用_Generic,C99的sin 可定义如下:

 

 

_Generic对第一个参数进行类型判断,然后根据从第二参数开始的类型-表达式关联表来进行编译期替换(或生成)。如果x为long double类型,那么_Generic(x, …)的结果为sinl,如果x为double类型,那么_Generic(x,…)的结果为sinf,否则结果为sin。可见_Generic实现就是一个generic selection。

有了_Generic,原本只有编译器才能玩的语法把戏,我们一样可以玩。例如编一个sum的数学接口,如下:

 

 

  如果_Generic中的参数可以支持更复杂的表达式,那就可以用来实现C++中的部分元编程,可惜它的参数表达式有限制。 不管怎么说_Generice是用来实现泛型宏的,而不是给开发人员任何变换的法戏,因此它的价值在于方便编写可移植的泛型宏。

Locations of visitors to this page
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值