我试图通过修改由 boost::property_tree 解析的 xml 配置文件来设置报告 std::chrono::duration 的单位。我当前的非编译解决方案尝试使用 std::variant 来执行此操作。
在.hpp类声明中
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;
}
我承认我不擅长元编程。有没有更简单的方法来做到这一点?本质上,我只能在编译时保证持续时间的类型将是持续时间类型的子集之一。
始终以足够的精度存储普通的
duration
。然后将输出缩放到所需的演示格式:
#include <boost/property_tree/xml_parser.hpp>
#include <chrono>
#include <iostream>
#include <map>
struct Program {
using duration = std::chrono::steady_clock::duration;
auto ReportingDuration(duration d) const {
using namespace std::chrono_literals;
using unit = decltype(1.ns); // or `duration` for integral
static std::map<std::string_view, unit> const units = {
{"ns", 1ns}, {"nanoseconds", 1ns}, //
{"us", 1us}, {"microseconds", 1us}, //
{"ms", 1ms}, {"milliseconds", 1ms}, //
{"s", 1s}, {"seconds", 1s}, //
{"m", 1min}, {"minutes", 1min}, //
{"h", 1h}, {"hours", 1h}, //
{"d", 24h}, {"days", 24h},
};
return d / units.at(reporting_unit_);
};
bool ReportingUnitValid() const try {
return ReportingDuration(std::chrono::hours(24)), true;
} catch (...) {
return false;
}
void SetupFunction(std::string const& filepath = "config.xml") {
boost::property_tree::ptree pt;
read_xml(filepath, pt);
reporting_unit_ = pt.get<std::string>("Config.ReportingUnits");
if (!ReportingUnitValid())
throw std::runtime_error("Invalid reporting unit");
}
void OutputFunction() {
using namespace std::chrono_literals;
for (duration v : std::vector<duration> //
{ //
1ns, 1us, 1ms, 1s, //
1min, //
1h, 1h + 1min, //
1h + 1min + 1s, //
24h, 24h + 1min, 24h + 1min + 1s})
std::cout << std::setw(16) << v << ": " << ReportingDuration(v) << " " << reporting_unit_
<< std::endl;
}
private:
std::string reporting_unit_ = "s";
};
int main() {
std::cout << std::fixed;
Program p;
p.SetupFunction();
p.OutputFunction();
}
所有测试:
g++ -std=c++20 -O2 -Wall -pedantic -pthread main.cpp
for unit in d h m s ms us ns; do cat > config.xml <<< "<Config><ReportingUnits>$unit</ReportingUnits></Config>"; ./a.out; done
印刷:
1ns: 0 d
1000ns: 0 d
1000000ns: 0 d
1000000000ns: 0 d
60000000000ns: 0 d
3600000000000ns: 0 d
3660000000000ns: 0 d
3661000000000ns: 0 d
86400000000000ns: 1 d
86460000000000ns: 1 d
86461000000000ns: 1 d
1ns: 0 h
1000ns: 0 h
1000000ns: 0 h
1000000000ns: 0 h
60000000000ns: 0 h
3600000000000ns: 1 h
3660000000000ns: 1 h
3661000000000ns: 1 h
86400000000000ns: 24 h
86460000000000ns: 24 h
86461000000000ns: 24 h
1ns: 0 m
1000ns: 0 m
1000000ns: 0 m
1000000000ns: 0 m
60000000000ns: 1 m
3600000000000ns: 60 m
3660000000000ns: 61 m
3661000000000ns: 61 m
86400000000000ns: 1440 m
86460000000000ns: 1441 m
86461000000000ns: 1441 m
1ns: 0 s
1000ns: 0 s
1000000ns: 0 s
1000000000ns: 1 s
60000000000ns: 60 s
3600000000000ns: 3600 s
3660000000000ns: 3660 s
3661000000000ns: 3661 s
86400000000000ns: 86400 s
86460000000000ns: 86460 s
86461000000000ns: 86461 s
1ns: 0 ms
1000ns: 0 ms
1000000ns: 1 ms
1000000000ns: 1000 ms
60000000000ns: 60000 ms
3600000000000ns: 3600000 ms
3660000000000ns: 3660000 ms
3661000000000ns: 3661000 ms
86400000000000ns: 86400000 ms
86460000000000ns: 86460000 ms
86461000000000ns: 86461000 ms
1ns: 0 us
1000ns: 1 us
1000000ns: 1000 us
1000000000ns: 1000000 us
60000000000ns: 60000000 us
3600000000000ns: 3600000000 us
3660000000000ns: 3660000000 us
3661000000000ns: 3661000000 us
86400000000000ns: 86400000000 us
86460000000000ns: 86460000000 us
86461000000000ns: 86461000000 us
1ns: 1 ns
1000ns: 1000 ns
1000000ns: 1000000 ns
1000000000ns: 1000000000 ns
60000000000ns: 60000000000 ns
3600000000000ns: 3600000000000 ns
3660000000000ns: 3660000000000 ns
3661000000000ns: 3661000000000 ns
86400000000000ns: 86400000000000 ns
86460000000000ns: 86460000000000 ns
86461000000000ns: 86461000000000 ns
现场演示: