You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用boost::program_options解析std::chrono::duration遇编译问题

问题:Boost Program Options解析std::chrono::duration编译失败

环境信息

  • 系统:arm64-apple-darwin22.2.0
  • Boost版本:1.80.0
  • 编译器:Apple clang 14.0.0

需求

解析命令行中12h34m56s格式的输入,转换为std::chrono::duration<int>对象。

实现的validate函数

#include <boost/program_options.hpp>
#include <iostream>

namespace po = boost::program_options;
using Duration = std::chrono::duration<int>;

inline void validate(boost::any &value, const std::vector<std::string> &values, Duration* target_type) {
    using namespace std::chrono_literals;
    try {
        po::validators::check_first_occurrence(value);
        auto duration_str = po::validators::get_single_string(values);
        Duration duration = Duration::zero();
        std::string::size_type i = 0;
        while (i < duration_str.size()) {
            std::string::size_type j = i;
            while (j < duration_str.size() && std::isdigit(duration_str[j])) {
                ++j;
            }
            int v = std::stoi(duration_str.substr(i, j - i));
            i = j;
            if (i < duration_str.size() && duration_str[i] == 'h') {
                duration += v * 1h;
                ++i;
            } else if (i < duration_str.size() && duration_str[i] == 'm') {
                duration += v * 1min;
                ++i;
            } else if (i < duration_str.size() && duration_str[i] == 's') {
                duration += v * 1s;
                ++i;
            }
        }
        value = boost::any(duration);
    } catch (...) {
        throw po::invalid_option_value("Invalid duration");
    }
}

主函数代码

int main(int ac, char *av[])
{
    try
    {
        po::options_description desc("Allowed options");
        desc.add_options()
            ("help,h", "produce a help screen")
            ("duration,d", po::value<Duration>(), "duration in 12h34m56s format")
            ;

        po::variables_map vm;
        po::store(po::parse_command_line(ac, av, desc), vm);
        if (vm.count("help"))
        {
            std::cout << desc;
            return 0;
        }
        if (vm.count("duration"))
        {
            std::cout << "The duration is \""
                 << vm["duration"].as<Duration>().count()
                 << "\"\n";
        }
    }
    catch (std::exception& e)
    {
        std::cout << e.what() << "\n";
    }

    return 0;
}

编译报错信息

/opt/homebrew/include/boost/lexical_cast/detail/converter_lexical.hpp:243:13: error: static_assert failed due to requirement 'has_right_shift<std::istream, std::chrono::duration<int, std::ratio<1, 1>>, boost::binary_op_detail::dont_care>::value || boost::has_right_shift<std::wistream, std::chrono::duration<int, std::ratio<1, 1>>, boost::binary_op_detail::dont_care>::value' "Target type is neither std::istream`able nor std::wistream`able"
            BOOST_STATIC_ASSERT_MSG((result_t::value || boost::has_right_shift<std::basic_istream<wchar_t>, T >::value),
            ^                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

尝试的解决方法

  • 最初尝试为std::chrono::duration<int>实现istream的operator>>以及重载boost::lexical_cast,未成功。
  • 后续尝试让该类型支持std::istream和std::wistream(编译器不支持std::chrono::from_stream),实现代码如下:

解析函数

template <typename String>
inline Duration parseDuration(const String& duration_str)
{
    using namespace std::chrono_literals;
    Duration duration;
    typename String::size_type i = 0;
    while (i < duration_str.size()) {
        std::wstring::size_type j = i;
        while (j < duration_str.size() && std::iswdigit(duration_str[j])) {
            ++j;
        }
        int v = std::stoi(duration_str.substr(i, j - i));
        i = j;
        if (i < duration_str.size() && duration_str[i] == 'h') {
            duration += v * 1h;
            ++i;
        } else if (i < duration_str.size() && duration_str[i] == 'm') {
            duration += v * 1min;
            ++i;
        } else if (i < duration_str.size() && duration_str[i] == 's') {
            duration += v * 1s;
            ++i;
        }
    }
    return duration;
}

流操作符重载

inline std::wistream& operator>>(std::wistream& is, Duration& duration) {
    std::wstring duration_str;
    is >> duration_str;
    duration = parseDuration(duration_str);
    return is;
}

inline std::istream& operator>>(std::istream& is, Duration& duration) {
    std::string duration_str;
    is >> duration_str;
    duration = parseDuration(duration_str);
    return is;
}

疑问

请问我忽略了哪些要点?

内容的提问来源于stack exchange,提问作者marital_weeping

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 15:55:14