std::ratio是编译期有理数类型,仅支持整数比值的静态表示与组合;它本质是std::intmax_t分子分母的类型包装器,所有运算(如ratio_add)在编译期完成并返回新ratio类型,不支持运行时计算、浮点约分或溢出保护。

std::ratio 是什么,它真能做“编译期比例计算”?
能,但不是你想的那种“计算”。std::ratio 本质是类型——它不存数值,只编码两个整型常量 Numerator 和 Denominator,全部在编译期确定。它不支持运行时输入、不支持浮点约简、也不直接参与算术运算。你拿到的永远是一个新类型,比如 std::ratio 表示 3/4,但它本身不是 0.75。
常见误解是把它当“编译期计算器”用,结果发现不能 auto x = std::ratio + std::ratio —— 这会编译失败。加减乘除都得靠配套的模板别名,比如 std::ratio_add。
怎么用 ratio_add / ratio_multiply 等模板做四则运算?
所有运算都返回新的 std::ratio 类型,分子分母自动约到最简(通过 std::gcd)。关键点:必须显式套模板,不能用操作符。
-
std::ratio_add<:ratio>, std::ratio>::type</:ratio>→std::ratio -
std::ratio_multiply<:ratio>, std::ratio>::type</:ratio>→std::ratio(自动约分) -
std::ratio_divide<:ratio>, std::ratio>::type</:ratio>→std::ratio
注意:所有参数必须是 std::ratio 类型,传 int 或字面量会报错,例如 std::ratio_add<:ratio>, 3></:ratio> 不合法。
立即学习“C++免费学习笔记(深入)”;
为什么 std::nano / std::mega 这些预定义 ratio 能直接用?
它们是标准库定义的 typedef,比如:using nano = std::ratio;using mega = std::ratio;
这些类型常用于 std::chrono::duration,例如:std::chrono::duration<int std::nano></int> 表示纳秒精度的整数时长。它们本身不带值,只是单位标签——真正存储时间值的是 duration 实例。
容易踩的坑:
- 把 std::nano 当成数值用(如 int x = std::nano;)→ 编译失败
- 误以为 std::ratio 和 std::milli 等价 → 它们类型不同,不能混用,哪怕值相同
ratio 的实际用途到底在哪?
它几乎只服务于 std::chrono 和自定义维度系统(如物理量单位),极少单独使用。典型场景:
- 定义带单位的时长类型:
using us = std::chrono::duration<int64_t std::micro>;</int64_t> - 做类型安全的单位转换:
us u = std::chrono::nanoseconds{1000};→ 自动转换,编译期检查比例是否可约 - 构建维度模板(如
quantity<length std::ratio>></length>),此时ratio表达量纲幂次
如果你只是想算个 3/4 + 1/6 并得到 11/12,用 std::ratio 大材小用,直接写 constexpr 分数类更直白。它的价值在于类型层面的精确性和零开销抽象,而不是“方便算分数”。
最常被忽略的一点:所有 std::ratio 运算结果仍是类型,要提取分子分母得用 ::num 和 ::den 静态成员,而且它们是 constexpr intmax_t,不是普通变量。


















