std::chrono::floor是C++20引入的向下取整工具,将time_point对齐到指定duration精度的整数倍,如12:34:56.789s向下舍入到秒级得12:34:56.000s;仅作用于time_point,需传入目标精度duration,不支持直接对duration使用。

std::chrono::floor 是什么,它能做什么
std::chrono::floor 是 C++20 引入的时钟舍入工具,用于将一个时间点(std::chrono::time_point)向下取整到指定精度的倍数。它不是四舍五入,也不是截断(trunc),而是严格向下对齐——比如把 12:34:56.789s 向下舍入到秒级,结果是 12:34:56.000s;舍入到分钟级,就是 12:34:00.000s。
它只作用于 time_point,不能直接用于 duration(除非你先构造出一个以 epoch 为起点的 time_point)。常见误用是试图对 std::chrono::system_clock::now().time_since_epoch()(返回 duration)直接调用 floor,这会编译失败。
如何正确调用 std::chrono::floor
必须传入两个参数:一个 time_point 和一个代表目标精度的 duration 类型(或其字面量)。编译器靠这个 duration 推导舍入粒度。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
auto now = std::chrono::system_clock::now(); auto floored_to_second = std::chrono::floor<std::chrono::seconds>(now); auto floored_to_5minutes = std::chrono::floor<std::chrono::minutes>(now); // ❌ 错!这是按分钟舍入,不是“每5分钟” auto floored_to_5minutes = std::chrono::floor<std::chrono::duration<int, std::ratio<300>>>(now); // ✅ 正确:300秒=5分钟
-
std::chrono::floor<t></t>中的T必须是duration类型,不能是time_point - 想实现“每 N 单位”舍入(如每5秒、每10毫秒),得用
std::chrono::duration自定义Period,例如std::ratio表示5秒,std::ratio<1, 100>表示10毫秒 - 如果目标精度比原
time_point的时钟精度还高(比如对system_clock用nanoseconds),不会报错,但实际精度受限于底层时钟
常见错误和兼容性陷阱
- 编译报错
no matching function for call to 'floor':大概率是传了 duration 而非 time_point,或者模板参数写成了 time_point 类型
- 在 C++17 或更早标准中使用会失败:
std::chrono::floor 是 C++20 特性,需确认编译器支持(GCC ≥10、Clang ≥11、MSVC ≥19.28)并开启 -std=c++20
- 对
steady_clock 使用没问题,但它舍入后的值仍属于该时钟体系,不可与 system_clock 混用比较或转换,否则行为未定义
- 舍入后的时间点仍是同一时钟类型,但内部
duration 值可能被截断;若原 time_point 已经是对齐的,floor 返回自身(无副作用)
替代方案:C++17 及以前怎么模拟 floor
no matching function for call to 'floor':大概率是传了 duration 而非 time_point,或者模板参数写成了 time_point 类型std::chrono::floor 是 C++20 特性,需确认编译器支持(GCC ≥10、Clang ≥11、MSVC ≥19.28)并开启 -std=c++20
steady_clock 使用没问题,但它舍入后的值仍属于该时钟体系,不可与 system_clock 混用比较或转换,否则行为未定义duration 值可能被截断;若原 time_point 已经是对齐的,floor 返回自身(无副作用)没有 std::chrono::floor 时,常用做法是手动除再乘:
立即学习“C++免费学习笔记(深入)”;
auto now = std::chrono::system_clock::now(); auto dur = now.time_since_epoch(); auto floored_dur = dur - (dur % std::chrono::seconds(1)); auto floored_tp = std::chrono::system_clock::time_point(floored_dur);
- 这里用
%求余,再减去余数,等价于向下取整 - 注意:负时间点(如某些测试中人为构造的早于 epoch 的时间)下,
%在 C++ 中向零取整,会导致结果偏大(即向上偏移),而floor始终向下,语义更可靠 - 所以即便在 C++20 环境,也建议优先用
std::chrono::floor,而不是手写算术逻辑
真正容易被忽略的是:floor 的模板参数决定了舍入单位,但这个单位必须能整除原时钟的周期(比如 system_clock 通常基于纳秒,用 hours 没问题,但用 std::ratio<1, 3>(约3.33ns)就可能因精度丢失导致意外截断)。

















