如何让std::chrono::duration的单位可配置?求简便实现方案
问题描述
我想通过boost::property_tree解析的XML配置文件,设置std::chrono::duration的输出单位。尝试用std::variant实现但代码编译失败,我不擅长元编程,有没有更简单的实现方式?本质上我能确定duration类型只会是指定的子集(秒、毫秒、微秒、纳秒)。
原尝试代码
头文件类声明
using TimestampVariant = std::variant< std::chrono::nanoseconds, std::chrono::microseconds, std::chrono::milliseconds, std::chrono::seconds >; TimestampVariant _timestamp_v;
cpp文件实现
auto GetTimestampVisitor = [](const auto& t) -> decltype(auto) { return std::chrono::duration_cast<std::remove_reference_t<decltype(t)>>(std::chrono::system_clock::now().time_since_epoch()).count(); }; void SetupFunction() { boost::property_tree::ptree property_tree; boost::property_tree::read_xml(filepath, property_tree); auto config = property_tree.get_child("Config"); std::string timestamp_type = config.get<std::string>("ReportingUnits"); if(!timestamp_type.compare("seconds") || !timestamp_type.compare("s")) { _timestamp_v = std::chrono::seconds(); } else if(!timestamp_type.compare("milliseconds") || !timestamp_type.compare("ms")) { _timestamp_v = std::chrono::milliseconds(); } else if(!timestamp_type.compare("microseconds") || !timestamp_type.compare("us")) { _timestamp_v = std::chrono::microseconds(); } else if(!timestamp_type.compare("nanoseconds") || !timestamp_type.compare("ns")) { _timestamp_v = std::chrono::nanoseconds(); } } void OutputFunction() { std::cout << std::visit(GetTimestampVisitor, _timestamp_v) << std::endl; }
更简单的实现方案
不用std::variant和访问者模式,改用枚举存储时间单位,输出时通过switch分支处理,代码更直观且无元编程复杂度:
步骤1:定义时间单位枚举
在类中添加枚举类型,替代variant成员:
enum class TimestampUnit { Seconds, Milliseconds, Microseconds, Nanoseconds }; TimestampUnit _timestamp_unit = TimestampUnit::Nanoseconds; // 设置默认单位
步骤2:修改配置解析逻辑
解析XML时直接设置枚举值:
void SetupFunction() { boost::property_tree::ptree property_tree; boost::property_tree::read_xml(filepath, property_tree); auto config = property_tree.get_child("Config"); std::string timestamp_type = config.get<std::string>("ReportingUnits"); if (timestamp_type == "seconds" || timestamp_type == "s") { _timestamp_unit = TimestampUnit::Seconds; } else if (timestamp_type == "milliseconds" || timestamp_type == "ms") { _timestamp_unit = TimestampUnit::Milliseconds; } else if (timestamp_type == "microseconds" || timestamp_type == "us") { _timestamp_unit = TimestampUnit::Microseconds; } else if (timestamp_type == "nanoseconds" || timestamp_type == "ns") { _timestamp_unit = TimestampUnit::Nanoseconds; } // 可选:添加else分支处理无效配置,比如报错或保持默认值 }
步骤3:修改输出逻辑
通过switch分支根据枚举值执行对应的duration转换:
void OutputFunction() { auto epoch_duration = std::chrono::system_clock::now().time_since_epoch(); switch (_timestamp_unit) { case TimestampUnit::Seconds: std::cout << std::chrono::duration_cast<std::chrono::seconds>(epoch_duration).count() << std::endl; break; case TimestampUnit::Milliseconds: std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(epoch_duration).count() << std::endl; break; case TimestampUnit::Microseconds: std::cout << std::chrono::duration_cast<std::chrono::microseconds>(epoch_duration).count() << std::endl; break; case TimestampUnit::Nanoseconds: std::cout << std::chrono::duration_cast<std::chrono::nanoseconds>(epoch_duration).count() << std::endl; break; } }
原代码编译失败原因
原代码中std::visit要求访问者的所有重载返回类型必须一致,但不同std::chrono::duration的count()返回值类型可能存在差异(比如部分编译器下不同单位的rep类型不同),导致编译报错。而枚举方案完全规避了这个问题,同时代码逻辑更易读。
内容的提问来源于stack exchange,提问作者SeedlessKiwi
相关产品推荐
相关产品推荐

