如何用boost::property_tree读取XML中的无限时长配置?
实现支持无限/有限时长的boost::property_tree读取方案
方法一:先读取字符串再判断(简单直接)
先读取字段的原始字符串,再根据内容判断是无限时长还是有限时长,适合快速实现:
boost::property_tree::ptree property_tree; boost::property_tree::read_xml(filepath, property_tree); auto config = property_tree.get_child("Config"); std::string duration_str = config.get<std::string>("MyDurationField"); std::chrono::seconds my_duration_value; bool is_infinite = false; // 兼容大小写的"inf"判断 if (duration_str == "inf" || duration_str == "INF") { is_infinite = true; // 用chrono秒的最大值标记无限时长,可根据业务需求替换 my_duration_value = std::chrono::seconds::max(); } else { try { // 转换为unsigned int后转成秒,处理非法输入 unsigned int sec = std::stoul(duration_str); my_duration_value = std::chrono::seconds(sec); } catch (const std::exception& e) { throw std::invalid_argument("非法的时长值: " + duration_str); } }
方法二:自定义Property Tree转换器(优雅复用)
通过实现boost::property_tree的自定义转换器,可直接用get方法读取带无限标记的时长,代码更整洁且复用性强:
定义转换器
#include <boost/property_tree/ptree.hpp> #include <chrono> #include <string> #include <stdexcept> struct DurationTranslator { using internal_type = std::string; using external_type = std::chrono::seconds; // 从字符串转换为时长,支持"inf" boost::optional<external_type> get_value(const internal_type& str) { if (str == "inf" || str == "INF") { return boost::make_optional(external_type::max()); } try { unsigned int sec = std::stoul(str); return boost::make_optional(external_type(sec)); } catch (...) { return boost::none; // 转换失败返回空,触发property_tree异常 } } // 反向转换(如需将时长写回XML时使用) boost::optional<internal_type> put_value(const external_type& dur) { if (dur == external_type::max()) { return boost::make_optional(std::string("inf")); } else { return boost::make_optional(std::to_string(dur.count())); } } };
使用转换器读取值
boost::property_tree::ptree property_tree; boost::property_tree::read_xml(filepath, property_tree); auto config = property_tree.get_child("Config"); // 用自定义转换器读取时长 std::chrono::seconds my_duration_value = config.get<std::chrono::seconds>( "MyDurationField", DurationTranslator() ); // 判断是否为无限时长 bool is_infinite = (my_duration_value == std::chrono::seconds::max());
补充:用std::optional标记无限时长
如果业务中可能用到接近seconds::max()的时长,可改用std::optional标记无限,避免冲突:
定义可选时长转换器
struct OptionalDurationTranslator { using internal_type = std::string; using external_type = std::optional<std::chrono::seconds>; boost::optional<external_type> get_value(const internal_type& str) { if (str == "inf" || str == "INF") { return boost::make_optional(external_type(std::nullopt)); } try { unsigned int sec = std::stoul(str); return boost::make_optional(external_type(std::chrono::seconds(sec))); } catch (...) { return boost::none; } } boost::optional<internal_type> put_value(const external_type& dur) { if (!dur.has_value()) { return boost::make_optional(std::string("inf")); } else { return boost::make_optional(std::to_string(dur->count())); } } };
使用示例
std::optional<std::chrono::seconds> my_duration_value = config.get<std::optional<std::chrono::seconds>>( "MyDurationField", OptionalDurationTranslator() ); if (!my_duration_value) { // 处理无限时长逻辑 } else { // 处理有限时长逻辑 }
内容的提问来源于stack exchange,提问作者SeedlessKiwi
相关产品推荐
相关产品推荐

