浏览代码

Add part code/text for 2.2.4

unknown 10 年之前
父节点
当前提交
41eafd2180
共有 2 个文件被更改,包括 65 次插入0 次删除
  1. 30 0
      CppTemplateTutorial.cpp
  2. 35 0
      ReadMe.md

+ 30 - 0
CppTemplateTutorial.cpp

@@ -207,6 +207,36 @@ namespace _2_2_3
 
 	template <> class TypeToID<int const * volatile * const volatile>;
 }
+
+namespace _2_2_4
+{
+	template <typename T> struct X {};
+	
+	template <typename T> struct Y
+	{
+		typedef X<T> ReboundType;
+		typedef typename X<T>::MemberType MemberType;
+#if WRONG_CODE_ENABLED
+		typedef WTF MemberType3;
+#endif
+
+		static void foo()
+		{
+			X<T> instance0;
+			X<T>::MemberType instan
+			WTF instance2
+			大王叫我来巡山 - + &
+		}
+	};
+
+	void foo()
+	{
+#if WRONG_CODE_ENABLED
+		Y<int>::foo();
+#endif
+	}
+}
+
 // 1.4 Specialization, Partial Specialization, Full Specialization
 namespace _1_4
 {

+ 35 - 0
ReadMe.md

@@ -1234,10 +1234,45 @@ void PrintID()
 但是呢,直觉对付更加复杂的问题还是没用的(也不是没用,主要是你没这个直觉了)。我们要把这个直觉,转换成合理的规则——即模板的匹配规则。
 当然,这个匹配规则是对复杂问题用的,所以我们会到实在一眼看不出来的时候才会动用它。一开始我们只要把握:模板是从最特殊到最一般形式进行匹配就可以了。
 
+####2.2.4 即用即推导
+
+这一节我们将讲述模板一个非常重要的行为特点:那就是什么时候编译器会对模板进行推导,推导到什么程度。
+
+这一知识,对于理解模板的编译期行为、以及修正模板编译错误都非常重要。
+
+我们先来看一个例子:
+
+``` C++
+template <typename T> struct X {};
+	
+template <typename T> struct Y
+{
+	typedef X<T> ReboundType;						// 类型定义1
+	typedef typename X<T>::MemberType MemberType;	// 类型定义2
+	typedef UnknownType MemberType3;				// 类型定义3
+
+	void foo()
+	{
+		X<T> instance0;
+		X<T>::MemberType instance1;
+		WTF instance2
+		大王叫我来巡山 - + &
+	}
+};
+```
+
+把这段代码编译一下,类型定义3出错,其它的都没问题。不过到这里你应该会有几个问题:
+
+1. 不是`struct X<T>`的定义是空的吗?为什么在`struct Y`内的类型定义2使用了 `X<T>::MemberType` 编译器没有报错?
+2. 类型定义2中的`typename`是什么鬼?为什么类型定义1就不需要?
+3. 为什么类型定义3会导致编译错误?
+4. 为什么`void foo()`在MSVC下什么错误都没报?
+
 
 ###2.3 函数模板的重载、参数匹配、特化与部分特化
 ###2.4 技巧单元:模板与继承
 
+
 ## 3   拿起特化的武器,去写程序吧!
 ###3.1 利用模板特化规则实现If-Then-Else与Switch-Case
 ###3.2 特化可以有多个选择:替换失败并不是一个错误,只是一种可能