[C/C++]在宏的参数中使用函数指针

typedef是C/C++中用于为现有类型创建更有意义的别名的关键字。对于普通类型来说,类型在左,别名在右。

typedef int size;

如果函数指针的定义也符合这种样式,那么下面下这样定义才是合理的:

   typedef void(*)(int) Type;

但实际上编译器采用的是如下的定义方式(以上的代码编译不过去的):

typedef void(*Ptr)(int);

至于原因,我认为(妄加猜测),void(*)(int)确实是一个函数指针,是一种类型,但是它还没有名字,而typedef的本意是对存在名字的类型给予别名,在这条规则下第一种定义方式显然是违背的。同样的还有对数组的重命名(本来应该是“typedef char[81] Line;”形式的,但由于同样的原因不能这样做):

   typedef char Line[81];

至于是不是编译器在技术实现上前一种比较困难,我就不得而知了。

回到本文档的主题上面来,我发现函数指针的这种命名方式不能用于实现某些宏,比如有一个宏PtrType也用来对类型重命名,其实现如下:

#define PtrType(_T, _Name) typedef _T _Name;

但实践结果却是:

PtrType(void(int), Ptr)   // 编译不过去

PtrType(void(*)(int), Ptr)   // 编译不过去
PtrType(int, Ptr)         // 这样可以的

typedef void(*PTR)(int);

PtrType(PTR, Ptr)         // 这样可以的

那么有没有办法让上面的宏依然生效呢?随着C++的发展,模板的概念被提出来,但是当把函数指针应用到模板的概念时却出现了问题:如果我们认为”void(int)”或者”void(*)(int)“不能表示自身的话,大名鼎鼎的function在使用上就会是另外一种方式。

function<int(int)> a; // 现在的使用方式

typdef int(*FT)(int); // 编译器不支持的
function<FT> a;

而实际上在应用于模板概念时,后面的这种方式”FT”被认成了”void”。很不可思议?”FT”明明是个指针呢!

我们且不追究这种概念上的不同意是为什么,又造成了多大的难以理解。但是这种方式却也恰恰能够解决我在本文中提出的这个问题。我们可以利用模板的这一个特性定义一个新的类型定义符号:$。

/**
* $,定义类型选择器
*/
template<class _T> struct $
{
/**
* 基本类型
*/
typedef _T Type;

/**
* 指针类型
*/
typedef _T *Ptr;

/**
* 引用类型
*/
typedef _T &Ref;
};

$的用法如下:

$<void(int)>::Ptr a = Print;
a(3);
$<int>::Type i = 0;
$<int>::Ref r = i;

我们使用这个符号对前面的PtrType进行改写:

#define PtrType(_T, _Name) typedef $<_T >::Ptr _Name;

这样就可以将函数指针用于宏的实现了:

PtrType(void(int), PTR)
PTR b = Print;
b(5);


转载于:https://my.oschina.net/lvan100/blog/330106

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值