std::ratio是编译期有理数类型,仅用于模板元编程中的比例标记与量纲推导,不支持运行时运算;其运算(如ratio_add、ratio_multiply)全在编译期完成,结果仍为std::ratio特化,典型应用是配合std::chrono::duration实现类型安全的时间单位换算。

std::ratio 是编译期比例类型,不是运行时计算工具
它不参与实际数值运算,只在模板元编程中表达“分子/分母”这个有理数概念。你不能用 std::ratio 直接算 3.5 * 2/3,也不能对它调用 .value() 得到浮点结果——它压根没有运行时实例。
常见误解是把它当计算器用,结果编译失败或行为诡异。真正用途是配合 std::chrono::duration 或自定义单位系统做类型安全的量纲推导。
用 std::ratio_add、std::ratio_multiply 等进行编译期分数运算
所有运算都在模板参数层面完成,结果仍是 std::ratio 类型,可直接用于静态断言或类型别名。
-
std::ratio_add<:ratio>, std::ratio>::type</:ratio>展开为std::ratio -
std::ratio_multiply<:ratio>, std::ratio>::type</:ratio>是std::ratio(已约分) - 除法用
std::ratio_divide,取负用std::ratio_negate - 所有操作数必须是
std::ratio特化,不能传整数或浮点字面量
std::ratio 的分子分母受 constexpr 整数限制
标准要求 std::ratio 的 Numerator 和 Denominator 必须是字面量整数常量表达式,且分母非零。但更关键的是:它们会被编译器用来做模板实例化,所以值不能溢出编译期整数范围。
立即学习“C++免费学习笔记(深入)”;
- GCC/Clang 对过大的值(如
std::ratio)可能报integer overflow in expression - 不能用变量或函数返回值构造
std::ratio,例如int x = 2; using r = std::ratio<x>;</x>是非法的 - 需要动态比例?得换运行时方案,比如
std::pair<int int></int>自行约分,或用boost::rational
和 std::chrono::duration 的联动才是典型使用场景
这是 std::ratio 最自然的落点:描述时间单位间的换算关系。例如 std::milli 就是 std::ratio,std::micro 是 std::ratio。
当你写 using ms = std::chrono::duration<int std::milli>;</int>,底层就靠 std::ratio 确保 ms(1) 精确等于 1 毫秒 —— 所有转换(如转成秒)都由编译期比例推导保证无精度丢失。
自己定义单位时也一样:using half_second = std::chrono::duration<int std::ratio>>;</int>,之后 half_second(3) 表示 1.5 秒,类型系统会阻止误加 std::milli 量纲的值。
真正难的是意识到 std::ratio 不是“用来算比例的”,而是“用来标记比例的”。一旦想让它干运行时的事,就得绕出去另找方案。


















