Note
1 MP
(1) 思想
`模板 用于 [1] 编译时计算 [2] 生成代码 (类和函数)`
1) 两级编程
2) 模板元编程 TMP
MP = "元数据" + 程序设计: 使用 他人 元程序/元编程结果, 不是 元编程
(2) 目的
[1] `类型安全` 提高
可 `计算` 数据结构或算法 所需 `确切类型` -> `消除` 很多 `显式类型转换`
[2] `运行时性能` 提高
1] `编译期计算` 并 `选择 运行时要调用的函数`
-> 将 `多态行为` 解析为 `直接 函数调用`
2] 用 `紧凑内存布局` 的 data structure
(3) vs GP
1) 区分的意义: 聚焦问题重点
—————————————————————————————————————————————————————————————————————————
| 关注的焦点 | 本质: 是一种 | 目的
—————————————————————————————————————————————————————————————————————————
[1] GP | 接口说明 | 设计 哲学 | 通用 类型 或 算法
—————————————————————————————————————————————————————————————————————————
[2] MP | 计算 | 编程/实现 技术 | 类型安全 + 运行时性能 高
—————————————————————————————————————————————————————————————————————————
2)
[1] GP 可划归为 MP 第1级: `无计算`
[2] 可支持 GP
对象分配构想 // 28.1 节
On_heap 和 Scoped 用于 Obj_holder
|_ _ _ _ _| |
| |
|/ |/
GP TMP
(4) 4 个等级
—————————————————————————————————————————————
[1] 无计算
仅 传递 `类型 和 值 实参`
—————————————————————————————————————————————
[2] `简单计算`: 类型 或 值 上
单位(Unit)相加 // 28.5 节
值上简单计算
———————————————————————————————————————————————————————————————
[3] `编译时检测` 的 计算
编译时选择器 std::conditional
———————————————————————————————————————————————————————————————
[4] `编译时迭代` 的 计算
阶乘 的 3种版本( 编译时计算, 版本2 还可以 运行时计算 )
———————————————————————————————————————————————————————————————
(5) 2 种实现
1] constexpr 函数 -> `只接受值, 且 只生成值` -> 优选 constexpr 函数, 而不是 TMP
2] 模板 -> TMP
(6) 过度使用
MP + 宏
|
|
|/
隐藏 `实现细节 + 糟糕的命名`
|
| 解决: 系统化的技术
|/
(类型)别名 + 特例化
2 编译时计算
(1) 优选 constexpr 函数, 而非 `模板`
(2) 尽可能 `隐藏` constexpr 函数中 `TMP 实现细节`
template<typename T>
constexpr bool Is_pod()
{
return std::is_pod<T>::value;
} |
|/
TMP
3 模板
(1) 目标
[1] 通用性
[2] 生成最优代码
(2) vs FP ( 函数式编程 )
模板 构成了完整的 `编译时 FP`
28.1 类型函数: 接受 (多个)类型参数 / 生成 (多个)类型结果
(1) 接受 `类型参数` -> 返回 `类型实参` 的 `关联成员 值/类型 ::value/::type`
(2) 广义形式: 模板类( 如 iterator_traits ) -> 关联(成员)类型 (别名)
1 类型 别名: 提取 类型 typename ::type
模板别名
[1] `更像 类型`
[2] 隐藏 ::type 实现细节
// 条件 true, 选则 T, else F
template<bool C, typename T, typename F>
using Conditional = typename std::conditional<C, T, F>::type;
2 类型 谓词: 提取 值 ::value
谓词: 返回 bool 值 的 (类) 函数
std::is_pod<T>::value 是 `POD 类型` 吗 ?
std::is_polymorphic<T>::value 是 `多态类型` 吗 ?
封装: `模板函数 + constexpr`
[1] 统一表示 Is_pod<T>()
[2] 隐藏实现细节
template<typename T>
constexpr bool Is_pod()
{
return std::is_pod<T>::value;
}
综合 Conditional & Is_pod<T>()
Conditional<Is_pod<T>(), On_heap<T>, Scoped<T> > x;
3 选择 函数(对象): 编译时选择 -> {} 构造 函数对象 -> () 调用 operator()
Conditional<(sizeof(int) > 4), X, Y>{}(3);
using Type = Conditional<(sizeof(int) > 4), X, Y>;
Type t;
t(3);
struct X
{
void operator()(int x) { /**/ }
};
// Y 类似
4 萃取 traits: 提取类型 的 associated type
萃取
及其 等价特性
( auto / decltype() ):
(1) 目的: 将 1个 类型(属性: value_type)
与 another 类型(迭代器: T*)
关联起来
(2) 应用: 非侵入式 添加类型: not change 目的类型/Iterator
template<typename Iterator>
struct iterator_traits
{
using value_type = typename Iterator::value_type;
};
template<typename T>
using Value_type = typename std::iterator_traits<T>::value_type;
// ... Difference_type
template<typename Iter>
Iter search(Iter p, Iter q, Value_type<Iter> val)
{
Difference_type<Iter> m = q - p;
// ...
}
|
| auto / decltype()
|/
template<typename Iter, typename Val>
Iter search(Iter p, Iter q, Val val)
{
auto m = q - p; // 若 不需要 命名 q - p 的 类型
using difference_type = decltype(q - p); // 若 需要 命名 q - p 的 类型
// ...
}
28.2 控制结构
1 选择
(1) 运行时选择: 普通 if 对 类型选择 无效
, 因 if 语句分支 不能
是 声明 作 唯一语句
if(My_cond<T>() )
using type = Square; // error
else
using type = Cube;
type x; // error
(2) 编译时选择器
Conditional<My_cond<T>(), Square, Cube>{}(99); // Ctor + operator()
My_cond<T>() ? Square{}(99) : Cube{}(99);
// error
( My_cond<T>() ? Square : Cube ){}(99); // ?: 后 2各操作数 不是表达式 -> 语法错
|
( My_cond<T>() ? Square{} : Cube{} )(99); // ?: 后 2各操作数 类型不相容 -> 语法错
2 迭代 和 递归: 编译时迭代
用 递归
实现
阶乘3版本
version1: TMP + constexpr 函数(模板)
version2: MP: constexpr 函数 - 条件运算符 ? ::
version3: 类(struct)模板
比较
version1/3 只支持 `编译时求值`, version2 还支持 `运行时求值`
version1/2 性能一样 -> version2 更清晰
// === version1
template<int N>
constexpr int fac()
{
return N*fac<N-1>();
}
template<>
constexpr int fac<1>()
{
return 1;
}
constexpr int x1 = fac<5>();
// === version2
constexpr int fac(int i)
{
return (i<2) ? 1: fac(i - 1);
}
constexpr int x2 = fac(5);
// === version3
template<int N>
struct Fac
{
static const int value = N*Fac<N-1>::value;
};
template<>
struct Fac<1>
{
static const int value = 1;
};
constexpr int x3 = Fac<5>::value;
28.3 编译时 列表: Tuple/元组
1 简单输出函数
2 元素访问
3 make_tuple
28.4 可变参数模板
1 类型安全的 printf()
2 机制
2种 参数包
模板参数包 typename... Args
函数参数包 ... args
... 0或多个
(1) use 第1个 elem
(2) (函数)参数包展开: args... -> 递归调用
[1] 剥离 headElem
[2] left 实参 捆包到 (函数)参数包 ...args
28.5 国际标准单位 例子
1 Unit
![](https://img.haomeiwen.com/i20172887/1b677d021d31a64c.png)
![](https://img.haomeiwen.com/i20172887/c61f18abd885d4dd.png)
![](https://img.haomeiwen.com/i20172887/22978408acc45964.jpg)
![](https://img.haomeiwen.com/i20172887/074eef2a587a2894.jpg)
![](https://img.haomeiwen.com/i20172887/3eb90f4d083d6751.jpg)
![](https://img.haomeiwen.com/i20172887/084180764d217327.jpg)
![](https://img.haomeiwen.com/i20172887/ea09f90c9fd26d0f.jpg)
![](https://img.haomeiwen.com/i20172887/4f1b9789e9976188.jpg)
![](https://img.haomeiwen.com/i20172887/d80319d5193f8135.jpg)
![](https://img.haomeiwen.com/i20172887/b3d0b61de98559cc.jpg)
![](https://img.haomeiwen.com/i20172887/64a9afbb12d935fc.jpg)
![](https://img.haomeiwen.com/i20172887/8fc448dedee962cf.jpg)
![](https://img.haomeiwen.com/i20172887/cd1e9778f2b377c1.jpg)
![](https://img.haomeiwen.com/i20172887/7df09aad7680761d.jpg)
![](https://img.haomeiwen.com/i20172887/f11bcda1ec0bc95a.jpg)
![](https://img.haomeiwen.com/i20172887/2a2a8c84bf41c4d9.jpg)
![](https://img.haomeiwen.com/i20172887/ff1e2b37aa4dd377.jpg)
![](https://img.haomeiwen.com/i20172887/e3d9d406f957cfa4.jpg)
网友评论