【问题标题】:Parsing std::chrono::duration with boost::program_options使用 `boost::program_options` 解析 `std::chrono::duration`
【发布时间】:2023-01-11 23:23:26
【问题描述】:

我正在尝试使用 boost::program_optionsboost 版本 1.80.0,Apple clang 14.0.0 arm64-apple-darwin22.2.0)解析命令行,以便读取格式为 12h34m56sstd::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),
            ^                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

我也尝试过实现 istream operator&gt;&gt; 以及为 std::chrono::duration&lt;int&gt; 类重载 boost::lexical_cast 但没有成功。我在这里错过了什么?

【问题讨论】:

    标签: c++ boost


    【解决方案1】:

    您得到的错误似乎是您没有为 std::wistream 定义的 operator&gt;&gt;(即错误消息中的 std::basic_istream&lt;wchar_t&gt;)。

    此外,您可以使用 from_stream 从流中提取 std::chrono::duration。这样就可以很容易地代替您手动解析代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-03
      • 2016-07-20
      • 1970-01-01
      • 1970-01-01
      • 2012-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多