C++11 模板元编程 - 元函数


我们继续演进前面那个无聊的类型计算的例子,来得出元函数的定义。

前面我们实现了PointerOf,它对于传进的任意类型T可以计算出T的指针类型。

template<typename T>
struct PointerOf
{
    using Result = T*;
};

现在我们想要实现一个能够计算T的指针的指针类型的模板,怎么做?

一种做法是直接定义一个新的模板:

template<typename T>
struct Pointer2Of
{
    using Result = T**;
};

为了让类型计算结果更像是出自函数的返回值,我们将计算结果的类型别名后续统一叫做Result。上述类模板本质上是一个对类型进行计算的函数:

Pointer2Of :: (typename T) => T -> T**

可以这样使用该函数:

int* pi;
Pointer2Of<int>::Result ppi = &pi

上述代码中Pointer2Of<int>::Result的计算发生在编译期,当在C++运行期前它已经得到计算结果int**了。所以上述代码在编译器计算完成后,就相当于如下代码:

int* pi;
int** ppi = &pi

虽然我们把类模板当做编译期函数来看,但是这种函数语法看起来和我们熟悉的函数相差较大,但究其本质和函数调用并无差异,都是为函数传入符合要求的实参,获得函数返回结果。

我们可以认为由于圆括号已经优先给了运行时C++函数,所以这种编译期C++函数的定义和调用都使用尖括号,并且需要显示调用Result才对函数进行运算求值。当使用这种编译期函数但并不调用Result时,和在“运行期C++”中使用一个函数指针类似,仅用做保存和传递用,但并不求值。

编译期函数计算,可以调用已有的其它编译期函数。如下通过嵌套调用PointerOf,也可以实现Pointer2Of:

template<typename T>
struct Pointer2Of
{
    using Result = typename PointerOf<typename PointerOf<T>::Result>::Result;
};

上面我们通过嵌套调用两次PointerOf来完成Pointer2Of的实现。在Pointer2Of中我们每次使用PointerOf<...>::Result时前面都用了typename关键字。原因是一旦PointerOf后面的尖括号中存在非具体类型的话,那么PointerOf的内部类型Result就是一个推导类型。C++标准要求使用推导类型前面必须使用typename关键字显示指明这是一个类型。所以我们在Pointer2Of中使用PointerOf完整的方式是这样的:typename PointerOf<...>::Result

和Haskell相比,我们必须得承认C++的这种函数式编程的书写确实太繁琐了。为了简化对元函数的使用,我们可以用宏封装一下PointerOf:

#define __pointer(...) typename PointerOf<__VA_ARGS__>::Result

这样Pointer2Of的定义可以简化如下:

template<typename T>
struct Pointer2Of
{
    using Result = __pointer(__pointer(T));
};

现在看起来好多了,__pointer(T)的写法更像是在调用一个函数。

可以看到我们对类模板进行约束,固定用Result保存计算结果,且只返回单一结果,可以使我们将模板当做函数使用时的写法得到统一,这对于我们进行函数组合简直是必须的。

后续我们将一直把这种在编译期进行计算,靠Result返回计算结果的类模板看作是编译期的函数,它的目的是为了支持C++模板元编程。为了和C++运行时函数进行区分,后文中我们统一将其称作元函数

如同函数是函数式编程的构成基础一样,元函数是C++模板元编程的构成基础。


高阶函数

返回 C++11模板元编程 - 目录

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容