如何更简洁地用毫秒、小时表示C++时长并适配fmt库?
问题:简化C++ chrono时长单位表示并适配fmt库
给定以下用于打印毫秒和小时单位时长的C++代码:
#include <iostream> #include <chrono> #include <thread> using namespace std; using namespace std::chrono; int main() { auto t0 = high_resolution_clock::now(); this_thread::sleep_for(300ms); auto t1 = high_resolution_clock::now(); cout << duration<float, milli>{t1-t0}.count() << "\n"; cout << duration<float, ratio<3600>>{t1-t0}.count() << "\n"; }
需求:
- 用更简洁的写法替代繁琐的
ratio<3600>,希望直接使用包含hour的写法 - 让方案适配fmt库,解决
t1-t0无法直接用于fmt的问题 - 理解为何
duration<float, hour>不能像duration<float, milli>那样使用
解答
1. 为何duration<float, hour>报错?
std::chrono::hour是一个完整的duration类型别名(定义为duration<long long, ratio<3600>>),而duration模板的第二个参数需要的是ratio类型(比如milli是ratio<1,1000>的别名),不是完整的duration类型。因此直接写duration<float, hour>会触发模板参数不匹配的错误,正确的做法是用hour对应的ratio——hours::period。
2. 简化时长单位的写法
可以利用标准库预定义的时间单位别名,结合直接构造对应浮点类型的duration,避免手动写ratio<3600>:
方法1:直接使用预定义period构造浮点duration
// 替代ratio<3600>,用hours::period获取小时对应的ratio cout << duration<float, hours::period>{t1 - t0}.count() << " hours\n"; // 毫秒的写法可以保持不变,或者统一风格 cout << duration<float, milliseconds::period>{t1 - t0}.count() << " ms\n";
方法2:自定义浮点时间单位别名(更简洁)
提前定义常用的浮点时间单位,代码可读性更高:
using float_milliseconds = std::chrono::duration<float, std::chrono::milliseconds::period>; using float_hours = std::chrono::duration<float, std::chrono::hours::period>; // 使用时直接转换 cout << float_milliseconds{t1 - t0}.count() << " ms\n"; cout << float_hours{t1 - t0}.count() << " hours\n";
3. 适配fmt库的方案
fmt库从版本9开始支持std::chrono类型的格式化,只需包含<fmt/chrono.h>,无需手动调用count(),还能直接指定输出格式:
完整示例代码
#include <iostream> #include <chrono> #include <thread> #include <fmt/chrono.h> using namespace std; using namespace std::chrono; // 自定义浮点时间单位别名(可选) using float_milliseconds = duration<float, milliseconds::period>; using float_hours = duration<float, hours::period>; int main() { auto t0 = high_resolution_clock::now(); this_thread::sleep_for(300ms); auto t1 = high_resolution_clock::now(); auto elapsed = t1 - t0; // 标准iostream输出 cout << float_milliseconds{elapsed}.count() << " ms\n"; cout << float_hours{elapsed}.count() << " hours\n"; // fmt库输出(直接格式化duration,支持多种格式) fmt::print("fmt输出(自动单位):{}\n", elapsed); fmt::print("fmt输出(显式毫秒):{:.2f} ms\n", float_milliseconds{elapsed}); fmt::print("fmt输出(显式小时):{:.6f} hours\n", float_hours{elapsed}); }
关键说明
- 必须包含
<fmt/chrono.h>才能让fmt支持chrono类型 - fmt支持直接格式化
std::chrono::duration对象,也支持格式化转换后的浮点duration类型 - 可以通过格式字符串指定精度和单位,比如
{:.2f} ms控制保留两位小数
内容的提问来源于stack exchange,提问作者Paul Jurczak
相关产品推荐
相关产品推荐

