使用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
相关产品推荐
相关产品推荐

