TL;DR

  1. DuckDB 大量使用 template,但目的通常很实际。
  2. 数据库执行引擎有很多“形状相同、物理类型不同”的 primitive。
  3. Template 让源码保持紧凑,同时让编译器生成直接的 typed code。

数据库里的问题

执行引擎会反复需要这些操作:

  • integer comparison
  • decimal arithmetic
  • string operation
  • aggregate update
  • hash probe
  • vectorized unary/binary operation

算法形状经常相同,变化的是物理类型。

如果每种组合都手写,代码会大量重复。正确性也更难保证,因为每份手工复制的代码都可能慢慢漂移。

Template 带来的东西

Template 可以表达这种模式:

same algorithm shape
different physical type
different operation

编译器再为实际类型生成特化代码。这对数据库很重要,因为很多 primitive 在 tight loop 里运行。很小的抽象成本也可能被放大。

这也是 if constexpr 有用的地方。普通 if 要求两个分支都能通过类型检查。if constexpr 可以让编译器丢掉当前类型不需要的分支。

这样一个 template 就能覆盖 signed/unsigned、不同 aggregate state、不同 vector operation,而不需要一堆手工 specialization。

Template 不能解决什么

Template 不能替代好的执行布局。

DuckDB 仍然需要 vector、validity mask、selection vector、string heap、hash table payload layout 和 memory accounting。Template 只是帮助表达 typed operation,不能把糟糕的物理布局变快。

Template 也有成本:

  • 编译时间更长
  • 生成代码可能更大
  • 错误信息更难读
  • ABI 和模块边界需要更小心

所以合理的使用范围很窄:primitive、type dispatch,以及真的需要 specialization 的 hot typed kernel。

边界

一个简单说法是:

Template 不是数据库引擎。
Template 是写数据库引擎内部 typed primitive 的工具。

对 DuckDB 来说,这是合理的 C++ 取舍。