|  | @@ -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 技巧单元:模板与继承
 |