Skip to content

Latest commit

 

History

History
88 lines (59 loc) · 2.96 KB

14.第十四章:元编程.md

File metadata and controls

88 lines (59 loc) · 2.96 KB

第十四章:元编程

1.元编程的引入

  1. 从泛型编程到元编程

    1. 泛型编程:使用一套代码处理不同类型
    2. 对于一些特殊的类型需要引入额外的处理逻辑——引入操纵程序的程序
    3. 元编程与编译期计算
  2. 第一个元程序示例(Erwin Unruh)

    1. 在编译错误中产生质数
  3. 使用编译期运算辅助运行期计算

    1. 不是简单地将整个运算一分为二
    2. 详细分析哪些内容可以放到编译期,哪些需要放到运行期
      1. 如果某种信息需要在运行期确定,那么通常无法利用编译期计算
  4. 元程序的形式

    1. 模板, constexpr 函数,其它编译期可使用的函数(如 sizeof )
    2. 通常以函数为单位,也被称为函数式编程
  5. 元数据

    1. 基本元数据:数值、类型、模板
    2. 数组
  6. 元程序的性质

    1. 输入输出均为 "常量"
    2. 函数无副作用
  7. type_traits元编程库

    1. C++11 引入到标准中,用于元编程的基本组件

2.顺序、分支、循环代码的编写方式

  1. 顺序代码的编写方式

    1. 类型转换示例:为输入类型去掉引用并添加 const
    2. 代码无需至于函数中
      1. 通常置于模板中,以头文件的形式提供
    3. 更复杂的示例:
      1. 以数值、类型、模板作为输入
      2. 以数值、类型、模板作为输出
    4. 引入限定符防止误用
    5. 通过别名模板简化调用方式
  2. 分支代码的编写方式

    1. 基于 if constexpr 的分支:便于理解只能处理数值,同时要小心引入运行期计算
    2. 基于(偏)特化引入分支:常见分支引入方式但书写麻烦
    3. 基于 std::conditional 引入分支:语法简单但应用场景受限
    4. 基于 SFINAE 引入分支
      1. 基于 std::enable_if 引入分支:语法不易懂但功能强大
        1. 注意用做缺省模板实参不能引入分支!
      2. 基于 std::void_t 引入分支: C++17 中的新方法,通过 "无效语句" 触发分支
    5. 基于 concept 引入分支: C++20 中的方法
      1. 可用于替换 enable_if
    6. 基于三元运算符引入分支: std::conditional 的数值版本
  3. 循环代码的编写方式

    1. 简单示例:计算二进制中包含 1 的个数
    2. 使用递归实现循环
    3. 任何一种分支代码的编写方式都对应相应的循环代码编写方式
    4. 使用循环处理数组:获取数组中 id=0,2,4,6... 的元素
    5. 相对复杂的示例:获取数组中最后三个元素

3.减少实例化的技巧

  1. 为什么要减少实例化

    1. 提升编译速度,减少编译所需内存
  2. 相关技巧

    1. 提取重复逻辑以减少实例个数
    2. conditional 使用时避免实例化
    3. 使用 std::conjunction / std::disjunction 引入短路逻辑
  3. 其它技巧介绍

    1. 减少分摊复杂度的数组元素访问操作