現在,我們想實現一個元函數,可以返回char類型指定層數的指針類型。
template<int N>
struct CharPointer
{
using Result = typename Times<N, char, PointerOf>::Result;
};
如上,我們定義了元函數CharPointer,它是一個int型單參元函數。它的實現調用了Times,將其第二和第三個參數分別固定為char和PointerOf。
借助于繼承的特性,上面的代碼可以簡化為:
template<int N>
struct CharPointer :Times<N, char, PointerOf>
{
};
這種定義元函數的方式叫做元函數轉發。
如果借助using關鍵字,可以實現得更加簡單:
template<int N> using CharPointer = Times<N, char, PointerOf>;
這里我們直接對Times綁定第二和第三個參數后為其起了別名CharPointer。
在函數式編程里面,有個概念叫做函數柯里化(currying),是指一個函數接收部分參數后,并不立即求值,而是繼續返回另一個函數。
如下Haskell代碼定義了一個三數相乘的函數multiThree,它接收三個Int型參數返回它們的乘積:
multiThree :: Int -> Int -> Int -> Int
multiThree x y z = x * y * z
當我們將multiThree其中一個參數固定后,它就變成了一個二參函數。
ghci > let multiTwoWithNine = multiThree 9
ghci > multiTwoWithNine 2 3
我們使用using關鍵字實現元函數轉發,可以達到類似函數柯里化的效果。柯里化可以幫助更容易地復用函數,實現函數之間更低成本且更靈活的組合。
函數柯里化在函數式編程語言里的意義非常重要,和C++模板元編程里面的還是有區別的。例如在Haskell中,可以不用為柯里化函數定義別名,就直接將其作為另一個函數的參數傳遞,而在C++模板元編程里目前還做不到。
現在借助柯里化,我們重新實現Pointer2Of如下:
template<typename T> using Pointer2Of = Times<2, T, PointerOf>;
可以看到,所謂的Pointer2Of,其實就是把Times的第一個和第三個參數固定后,得到的單參柯里化函數。