AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / coding / 问题 / 79138323
Accepted
SeedlessKiwi
SeedlessKiwi
Asked: 2024-10-30 01:22:55 +0800 CST2024-10-30 01:22:55 +0800 CST 2024-10-30 01:22:55 +0800 CST

有没有简单的方法可以使 std::chrono::duration 的单位可配置?

  • 772

我试图通过修改 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;
}

我承认我不擅长元编程。有没有更简单的方法可以做到这一点?本质上,我只能在编译时保证持续时间的类型将是持续时间类型的子集之一。

boost
  • 1 1 个回答
  • 41 Views

1 个回答

  • Voted
  1. Best Answer
    sehe
    2024-10-30T06:18:30+08:002024-10-30T06:18:30+08:00

    由于存在通用表示,因此不需要元编程。

    只需始终存储具有足够精度的纯文本即可duration。然后在输出时缩放到所需的演示格式:

    在 Coliru 上直播

    #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.000000 d
              1000ns: 0.000000 d
           1000000ns: 0.000000 d
        1000000000ns: 0.000012 d
       60000000000ns: 0.000694 d
     3600000000000ns: 0.041667 d
     3660000000000ns: 0.042361 d
     3661000000000ns: 0.042373 d
    86400000000000ns: 1.000000 d
    86460000000000ns: 1.000694 d
    86461000000000ns: 1.000706 d
                 1ns: 0.000000 h
              1000ns: 0.000000 h
           1000000ns: 0.000000 h
        1000000000ns: 0.000278 h
       60000000000ns: 0.016667 h
     3600000000000ns: 1.000000 h
     3660000000000ns: 1.016667 h
     3661000000000ns: 1.016944 h
    86400000000000ns: 24.000000 h
    86460000000000ns: 24.016667 h
    86461000000000ns: 24.016944 h
                 1ns: 0.000000 m
              1000ns: 0.000000 m
           1000000ns: 0.000017 m
        1000000000ns: 0.016667 m
       60000000000ns: 1.000000 m
     3600000000000ns: 60.000000 m
     3660000000000ns: 61.000000 m
     3661000000000ns: 61.016667 m
    86400000000000ns: 1440.000000 m
    86460000000000ns: 1441.000000 m
    86461000000000ns: 1441.016667 m
                 1ns: 0.000000 s
              1000ns: 0.000001 s
           1000000ns: 0.001000 s
        1000000000ns: 1.000000 s
       60000000000ns: 60.000000 s
     3600000000000ns: 3600.000000 s
     3660000000000ns: 3660.000000 s
     3661000000000ns: 3661.000000 s
    86400000000000ns: 86400.000000 s
    86460000000000ns: 86460.000000 s
    86461000000000ns: 86461.000000 s
                 1ns: 0.000001 ms
              1000ns: 0.001000 ms
           1000000ns: 1.000000 ms
        1000000000ns: 1000.000000 ms
       60000000000ns: 60000.000000 ms
     3600000000000ns: 3600000.000000 ms
     3660000000000ns: 3660000.000000 ms
     3661000000000ns: 3661000.000000 ms
    86400000000000ns: 86400000.000000 ms
    86460000000000ns: 86460000.000000 ms
    86461000000000ns: 86461000.000000 ms
                 1ns: 0.001000 us
              1000ns: 1.000000 us
           1000000ns: 1000.000000 us
        1000000000ns: 1000000.000000 us
       60000000000ns: 60000000.000000 us
     3600000000000ns: 3600000000.000000 us
     3660000000000ns: 3660000000.000000 us
     3661000000000ns: 3661000000.000000 us
    86400000000000ns: 86400000000.000000 us
    86460000000000ns: 86460000000.000000 us
    86461000000000ns: 86461000000.000000 us
                 1ns: 1.000000 ns
              1000ns: 1000.000000 ns
           1000000ns: 1000000.000000 ns
        1000000000ns: 1000000000.000000 ns
       60000000000ns: 60000000000.000000 ns
     3600000000000ns: 3600000000000.000000 ns
     3660000000000ns: 3660000000000.000000 ns
     3661000000000ns: 3661000000000.000000 ns
    86400000000000ns: 86400000000000.000000 ns
    86460000000000ns: 86460000000000.000000 ns
    86461000000000ns: 86461000000000.000000 ns
    

    现场演示:

    请注意,视频仅在最后的部分时长内重新编译。

    • 1

相关问题

  • 独立 Boost.Asio + Boost.Beast

  • 为 Boost C++ 启用 OpenSSL FIPS 模式

  • 在 C++03 编译器上使用移动模拟将 boost::unique_lock 作为返回值从函数中移出是否安全?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    Vue 3:创建时出错“预期标识符但发现‘导入’”[重复]

    • 1 个回答
  • Marko Smith

    为什么这个简单而小的 Java 代码在所有 Graal JVM 上的运行速度都快 30 倍,但在任何 Oracle JVM 上却不行?

    • 1 个回答
  • Marko Smith

    具有指定基础类型但没有枚举器的“枚举类”的用途是什么?

    • 1 个回答
  • Marko Smith

    如何修复未手动导入的模块的 MODULE_NOT_FOUND 错误?

    • 6 个回答
  • Marko Smith

    `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它?

    • 3 个回答
  • Marko Smith

    何时应使用 std::inplace_vector 而不是 std::vector?

    • 3 个回答
  • Marko Smith

    在 C++ 中,一个不执行任何操作的空程序需要 204KB 的堆,但在 C 中则不需要

    • 1 个回答
  • Marko Smith

    PowerBI 目前与 BigQuery 不兼容:Simba 驱动程序与 Windows 更新有关

    • 2 个回答
  • Marko Smith

    AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String”

    • 1 个回答
  • Marko Smith

    我正在尝试仅使用海龟随机和数学模块来制作吃豆人游戏

    • 1 个回答
  • Martin Hope
    Aleksandr Dubinsky 为什么 InetAddress 上的 switch 模式匹配会失败,并出现“未涵盖所有可能的输入值”? 2024-12-23 06:56:21 +0800 CST
  • Martin Hope
    Phillip Borge 为什么这个简单而小的 Java 代码在所有 Graal JVM 上的运行速度都快 30 倍,但在任何 Oracle JVM 上却不行? 2024-12-12 20:46:46 +0800 CST
  • Martin Hope
    Oodini 具有指定基础类型但没有枚举器的“枚举类”的用途是什么? 2024-12-12 06:27:11 +0800 CST
  • Martin Hope
    sleeptightAnsiC `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它? 2024-11-09 07:18:53 +0800 CST
  • Martin Hope
    The Mad Gamer 何时应使用 std::inplace_vector 而不是 std::vector? 2024-10-29 23:01:00 +0800 CST
  • Martin Hope
    Chad Feller 在 5.2 版中,bash 条件语句中的 [[ .. ]] 中的分号现在是可选的吗? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench 为什么双破折号 (--) 会导致此 MariaDB 子句评估为 true? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng 为什么 `dict(id=1, **{'id': 2})` 有时会引发 `KeyError: 'id'` 而不是 TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String” 2024-03-20 03:12:31 +0800 CST
  • Martin Hope
    MarkB 为什么 GCC 生成有条件执行 SIMD 实现的代码? 2024-02-17 06:17:14 +0800 CST

热门标签

python javascript c++ c# java typescript sql reactjs html

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve