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);