typedef是C/C++中用于为现有类型建立更有意义的别名的关键字。对于普通类型来讲,类型在左,别名在右。
数组
typedef int size;
若是函数指针的定义也符合这种样式,那么下面下这样定义才是合理的:函数
typedef void(*)(int) Type;
但实际上编译器采用的是以下的定义方式(以上的代码编译不过去的):
指针
typedef void(*Ptr)(int);
至于缘由,我认为(妄加猜想),void(*)(int)确实是一个函数指针,是一种类型,可是它尚未名字,而typedef的本意是对存在名字的类型给予别名,在这条规则下第一种定义方式显然是违背的。一样的还有对数组的重命名(原本应该是“typedef char[81] Line;”形式的,但因为一样的缘由不能这样作):code
typedef char Line[81];
至因而不是编译器在技术实现上前一种比较困难,我就不得而知了。文档
回到本文档的主题上面来,我发现函数指针的这种命名方式不能用于实现某些宏,好比有一个宏PtrType也用来对类型重命名,其实现以下:编译器
#define PtrType(_T, _Name) typedef _T _Name;
io
但实践结果倒是:编译
PtrType(void(int), Ptr) // 编译不过去function
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);