我需要使用 boost::program_options
像 -value=str1,str2,str3
一样解析 cmd。我找到了 exactly the same question但它不再工作了( boost 1.55 和 1.56)。
我尝试定义自己的类和映射器,但没有成功:
namespace po = boost::program_options;
desc.add_options()
("mattr", po::value<lli::CommaSeparatedVector>(&MAttrs), "Target specific attributes (-mattr=help for details)");
namespace lli {
class CommaSeparatedVector
{
public:
// comma separated values list
std::vector<std::string> values;
};
}
void tokenize(const std::string& str, std::vector<std::string>& tokens, const std::string& delimiters = ",")
{
// Skip delimiters at beginning.
std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
// Find first non-delimiter.
std::string::size_type pos = str.find_first_of(delimiters, lastPos);
while (std::string::npos != pos || std::string::npos != lastPos) {
// Found a token, add it to the vector.
tokens.push_back(str.substr(lastPos, pos - lastPos));
// Skip delimiters.
lastPos = str.find_first_not_of(delimiters, pos);
// Find next non-delimiter.
pos = str.find_first_of(delimiters, lastPos);
}
}
// mapper for "lli::CommaSeparatedVector"
std::istream& operator>>(std::istream& in, lli::CommaSeparatedVector &value)
{
std::string token;
in >> token;
tokenize(token, value.values);
return in;
}
错误信息:
In file included from /softdev/boost-1.56/include/boost/program_options.hpp:15:
In file included from /softdev/boost-1.56/include/boost/program_options/options_description.hpp:13:
In file included from /softdev/boost-1.56/include/boost/program_options/value_semantic.hpp:14:
/softdev/boost-1.56/include/boost/lexical_cast.hpp:379:13: error: implicit instantiation of undefined template
'boost::STATIC_ASSERTION_FAILURE<false>'
BOOST_STATIC_ASSERT_MSG((result_t::value || boost::has_right_shift<std::basic_istream<wchar_t>, T >::value),
^
/softdev/boost-1.56/include/boost/static_assert.hpp:36:48: note: expanded from macro 'BOOST_STATIC_ASSERT_MSG'
# define BOOST_STATIC_ASSERT_MSG( B, Msg ) BOOST_STATIC_ASSERT( B )
^
/softdev/boost-1.56/include/boost/static_assert.hpp:169:13: note: expanded from macro 'BOOST_STATIC_ASSERT'
sizeof(::boost::STATIC_ASSERTION_FAILURE< BOOST_STATIC_ASSERT_BOOL_CAST( __VA_ARGS__ ) >)>\
^
/softdev/boost-1.56/include/boost/lexical_cast.hpp:406:44: note: in instantiation of template class
'boost::detail::deduce_target_char_impl<boost::detail::deduce_character_type_later<lli::CommaSeparatedVector> >'
requested here
typedef BOOST_DEDUCED_TYPENAME deduce_target_char_impl< stage1_type >::type stage2_type;
^
/softdev/boost-1.56/include/boost/lexical_cast.hpp:564:59: note: in instantiation of template class
'boost::detail::deduce_target_char<lli::CommaSeparatedVector>' requested here
typedef BOOST_DEDUCED_TYPENAME boost::detail::deduce_target_char<Target>::type target_char_t;
^
/softdev/boost-1.56/include/boost/lexical_cast.hpp:2067:40: note: in instantiation of template class
'boost::detail::lexical_cast_stream_traits<std::__1::basic_string<char>, lli::CommaSeparatedVector>' requested here
BOOST_DEDUCED_TYPENAME stream_trait::char_type,
^
/softdev/boost-1.56/include/boost/lexical_cast.hpp:2289:20: note: in instantiation of template class
'boost::detail::lexical_converter_impl<lli::CommaSeparatedVector, std::__1::basic_string<char> >' requested here
return caster_type::try_convert(arg, result);
^
/softdev/boost-1.56/include/boost/lexical_cast.hpp:2316:41: note: in instantiation of function template specialization
'boost::conversion::detail::try_lexical_convert<lli::CommaSeparatedVector, std::__1::basic_string<char> >' requested
here
if (!boost::conversion::detail::try_lexical_convert(arg, result))
^
/softdev/boost-1.56/include/boost/program_options/detail/value_semantic.hpp:89:21: note: in instantiation of function
template specialization 'boost::lexical_cast<lli::CommaSeparatedVector, std::__1::basic_string<char> >' requested here
v = any(lexical_cast<T>(s));
^
/softdev/boost-1.56/include/boost/program_options/detail/value_semantic.hpp:167:13: note: in instantiation of function
template specialization 'boost::program_options::validate<lli::CommaSeparatedVector, char>' requested here
validate(value_store, new_tokens, (T*)0, 0);
^
/softdev/boost-1.56/include/boost/program_options/detail/value_semantic.hpp:182:33: note: in instantiation of member function
'boost::program_options::typed_value<lli::CommaSeparatedVector, char>::xparse' requested here
typed_value<T>* r = new typed_value<T>(v);
^
./lib_lli.cpp:480:23: note: in instantiation of function template specialization
'boost::program_options::value<lli::CommaSeparatedVector>' requested here
("mattr", po::value<lli::CommaSeparatedVector>(&MAttrs), "Target specific attributes (-mattr=help for details)");
^
/softdev/boost-1.56/include/boost/static_assert.hpp:87:26: note: template is declared here
template <bool x> struct STATIC_ASSERTION_FAILURE;
^
1 warning and 1 error generated.
最佳答案
您必须使 operator>>
可被发现。
因为它需要在 std::istream&
的左侧操作,所以不能在“拥有”类中声明;但作为一项免费功能,您将需要使用 namespace 查找,以便代码找到流式处理运算符。
现在请注意,流运算符是从命名空间 boost::detail
中的某处调用的(来自 Boost Lexicalcast 库)。
它使用参数依赖查找 来选择重载。 ADL 意味着与参数类型关联的 namespace 指示应搜索哪些 namespace 以查找候选运算符 >> 重载。¹
这意味着查找将搜索命名空间 std
(由于 std::istream
参数)以及 lli
(由于第二个参数类型)。请注意,如果任何参数 types 本身使用 template argument 类型,则定义 that 的 namespace 也包含在查找中。
正如您所说,您可以解决这个问题
- 不使用 namespace 。
- 或者,您可以在
lli
命名空间内定义运算符>> 重载: Live On Coliru - 或者,在类中声明它(作为 friend 静态函数,将被视为好像在包含的命名空间中声明): Live On Coliru
¹ 不过,它同样适用于非运算符(operator)自由功能
关于boost - 如何使用 boost::program_options 解析逗号分隔值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26389297/