撰写2.1节。

This commit is contained in:
unknown 2014-02-27 14:00:11 -08:00
parent f780813521
commit c3a9257a8a

View File

@ -514,6 +514,71 @@ template <float a> class E {}; // ERROR: 别闹!早说过只能是整数类
## 2. 模板元编程基础
###2.1 编程,元编程,模板元编程
技术的学习是一个登山的过程。第一章是最为平坦的山脚道路。而从这一章开始,则是正式的爬坡。无论是我写作还是你阅读,都需要付出比第一章更多的代价。那么问题就是,付出更多的精力学习模板是否值得?
这个问题很功利但是一阵见血。因为技术的根本目的在于解决需求。那C++的模板能做什么?
一个高的回答是C++里面的模板犹如C中的宏、C#和Java中的自省restropection和反射reflection一样是一个改变语言内涵拓展语言外延的存在。
程序最根本的目的是什么?复现真实世界或人所构想的规律,减少重复工作的成本,或通过提升规模完成人所不能及之事。但是世间之事万千,有限的程序如何重现复杂的世界呢?
答案是“抽象”。论及具体手段,无外乎“求同”与“存异”:概括一般规律,处理特殊情况。这也是软件工程所追求的目标。一般规律概括的越好,我们所付出的劳动也就越少。
同样的作为脑力劳动的产品程序本身也是有规律性的。《Modern C++ Design》中的前言就抛出了一连串有代表性的问题
```
如何撰写更高级的C++程式?
如何应付即使在很干净的设计中仍然像雪崩一样的不相干细节?
如何构建可复用组件,使得每次在不同程式中应用组件时无需大动干戈?
```
我们以数据结构举例。在程序里,你需要一些堆栈。这个堆栈的元素可能是整数、浮点或者别的什么类型。一份整型堆栈的代码可能是:
``` C++
class StackInt
{
public:
void push(Int v);
Int pop();
Int Find(Int x)
{
for(Int i = 1; i <= size; )
{
if(data[i] == x) { return i; }
}
}
// ... 其他代码 ...
};
```
如果你要支持浮点了,那么你只能将代码再次拷贝出来,并作如下修改:
``` C++
class StackFloat
{
public:
void push(Float v);
Float pop();
Int Find(Float x)
{
for(Int i = 1; i <= size; )
{
if(data[i] == x) { return i; }
}
}
// ... 其他代码 ...
};
```
当然也许你觉得这样做能充分体会代码行数增长的成就感。但是有一天,你突然发现:呀,`Find` 函数实现有问题了。怎么办?这个时候也许你只有两份这样的代码,那好说,一一去修正就好了。如果你有十个呢?二十个?五十个?
时间一长,你就厌倦了这样的生活。你觉得每个堆栈都差不多,但是又有点不一样。为了这一点点不一样,你付出了太多的时间。吃饭的时间,泡妞的时间,睡觉的时间,看岛国小电影顺便练习小臂力量的时间。
于是便诞生了新的技术,来消解我们的烦恼。
这个技术的名字,并不叫“模板”,而是叫“元编程”。
###2.2 模板世界的If-Then-Else类模板的特化与偏特化
###2.3 函数模板的重载、参数匹配、特化与部分特化
###2.4 技巧单元:模板与继承