使用宏进行类型通用编程:确定类型的技巧? [英] Type-generic programming with macros: tricks to determine type?

查看:123
本文介绍了使用宏进行类型通用编程:确定类型的技巧?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可以在 C 中使用某些类型的泛型函数作为宏,例如:

 (x)== sizeof(float)?sqrtf((x)):\ 
sizeof(x)== sizeof(double)?sqrt(x) (x)):\
sqrtl((x)))

大多数情况下)只要 x 是一个浮点类型。



但是如果我想要一个type-通用宏,可以采用整数类型或指针类型,可能具有相同的大小。有一种聪明的方法来测试宏参数是一个整数还是一个指针?你可以检测一个表达式是一个整型表达式还是一个<$ c

$ c $> char * 表达式,至少在从指针转换到 uintptr_t 的体系结构中定义明确:

  #define INT_OR_CHARP(X)(((uintptr_t)((X)+1) - (uintptr_t)(X))== 1)

这将检测 X 是否是指向< c $ c> T 与 sizeof(T)> 1 。这不适用于 void * 和其他角落案例。因为 X 会被评估两次,所以您必须注意副作用。为避免整数如果 X 是例如类型 signed int ,您可以替换(X) with

 (1?(X):(uintmax_t)0)
X
是一个整数表达式,这将是<$ c>类型的

$ C> uintmax_t型。然后 +1 可能会环绕,但结果总是定义良好,两部分之间的区别始终是 1 。如果 X 是一个指针表达式,那么这是因为任何值为 0 的常量整型表达式也是一个空指针常量



这总共给出了

 <$ c $ (uintptr_t)((1≤(x):(uintmax_t)0)+1) - (uintptr_t)(1≤(X):( uintmax_t)0))== 1) 


It's possible to do certain types of type-generic-functions as macros in C, for instance things like:

#define SQRT(x) (sizeof(x) == sizeof(float) ? sqrtf((x)) : \
                 sizeof(x) == sizeof(double) ? sqrt((x)) : \
                 sqrtl((x)) )

This works (mostly) as expected as long as x is a floating point type.

But what if I want a type-generic macro that can take either an integer type or a pointer type, which might have the same size. Is there a clever way to test whether the macro argument is an integer or a pointer? What about an integer versus a floating point type?

解决方案

You may detect if an expression is an integer expression or a char* expression, at least on architectures where cast from pointer to uintptr_t is well defined:

#define INT_OR_CHARP(X) (((uintptr_t)((X)+1) - (uintptr_t)(X)) == 1)

This will detect if X is a pointer to a type T with sizeof(T) > 1. This will not work for void* and other corner cases. And because X is evaluated two times you'd have to watch for side effects.

To avoid problems with integer overflow if X is e.g of type signed int you may replace (X) with

(1 ? (X) : (uintmax_t)0)

This guarantees that if X is an integer expression this will be of type uintmax_t. The +1 will then perhaps wrap around, but the result is always well defined and the difference between the two parts will always be 1. If X is a pointer expression, then this is so because any constant integer expression of value 0 is also a null pointer constant.

In total this gives

#define INT_OR_CHARP(X) (((uintptr_t)((1 ? (X) : (uintmax_t)0)+1) - (uintptr_t)(1 ? (X) : (uintmax_t)0)) == 1)

这篇关于使用宏进行类型通用编程:确定类型的技巧?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆