增加了3.1.3的内容

This commit is contained in:
wuye9036 2016-01-03 00:21:10 -08:00
parent d897a5cba3
commit 7224463f4f

View File

@ -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