Browse Source

增加了3.1.3的内容

wuye9036 9 years ago
parent
commit
7224463f4f
1 changed files with 72 additions and 3 deletions
  1. 72 3
      ReadMe.md

+ 72 - 3
ReadMe.md

@@ -1905,15 +1905,84 @@ template <
 > class Tuple;
 ```
 
-实际上,模板的默认参数不仅仅可以是一个确定的类型,它还能是以其他类型为参数的一个类型表达式。考虑下面的例子:
+实际上,模板的默认参数不仅仅可以是一个确定的类型,它还能是以其他类型为参数的一个类型表达式。
+考虑下面的例子:我们要执行两个同类型变量的除法,它对浮点、整数和其他类型分别采取不同的措施。
+对于浮点,执行内置除法;对于整数,要处理除零保护,防止引发异常;对于其他类型,执行一个叫做`CustomeDiv`的函数。
 
+第一步,我们先把浮点正确的写出来:
 ```C++
-template <typename T> struct IsFloat {
-    static bool const value = true;
+#include <type_traits>
+
+template <typename T> T CustomDiv(T lhs, T rhs) {
+    // Custom Div的实现
 }
 
+template <typename T, bool IsFloat = std::is_floating_point<T>::value> struct SafeDivide {
+    static T Do(T lhs, T rhs) {
+        return CustomDiv(lhs, rhs);
+    }
+};
+
+template <typename T> struct SafeDivide<T, true>{     // 偏特化A
+    static T Do(T lhs, T rhs){
+        return lhs/rhs;
+    }
+};
+
+template <typename T> struct SafeDivide<T, false>{   // 偏特化B
+    static T Do(T lhs, T rhs){
+        return lhs;
+    }
+};
+
+void foo(){
+    SafeDivide<float>::Do(1.0f, 2.0f);	// 调用偏特化A
+    SafeDivide<int>::Do(1, 2);          // 调用偏特化B
+}
 ```
 
+在实例化的时候,尽管我们只为`SafeDivide`指定了参数`T`,但是它的另一个参数`IsFloat`在缺省的情况下,可以根据`T`,求出表达式`std::is_floating_point<T>::value`的值作为实参的值,带入到`SafeDivide`的匹配中。
+
+嗯,这个时候我们要再把整型和其他类型纳入进来,无外乎就是加这么一个参数:
+
+```C++
+#include <complex>
+#include <type_traits>
+
+template <typename T> T CustomDiv(T lhs, T rhs) {
+    T v;
+    // Custom Div的实现
+    return v;
+}
+
+template <
+    typename T,
+    bool IsFloat = std::is_floating_point<T>::value,
+    bool IsIntegral = std::is_integral<T>::value
+> struct SafeDivide {
+    static T Do(T lhs, T rhs) {
+        return CustomDiv(lhs, rhs);
+    }
+};
+
+template <typename T> struct SafeDivide<T, true, false>{    // 偏特化A
+    static T Do(T lhs, T rhs){
+        return lhs/rhs;
+    }
+};
+
+template <typename T> struct SafeDivide<T, false, true>{   // 偏特化B
+    static T Do(T lhs, T rhs){
+        return rhs == 0 ? 0 : lhs/rhs;
+    }
+};
+
+void foo(){
+    SafeDivide<float>::Do(1.0f, 2.0f);	                          // 调用偏特化A
+    SafeDivide<int>::Do(1, 2);                                    // 调用偏特化B
+    SafeDivide<std::complex<float>>::Do({1.f, 2.f}, {1.f, -2.f}); // 调用一般形式
+}
+```
 
 ###3.2 后悔药:SFINAE
 ###3.3 实战单元:获得类型的属性——类型萃取(Type Traits)