【发布时间】:2023-01-11 23:23:26
【问题描述】:
我正在尝试使用 boost::program_options(boost 版本 1.80.0,Apple clang 14.0.0 arm64-apple-darwin22.2.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),
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
我也尝试过实现 istream operator>> 以及为 std::chrono::duration<int> 类重载 boost::lexical_cast 但没有成功。我在这里错过了什么?
【问题讨论】: