如何解决Boost::qi 解析字符串
标签样式:
#EXTINF:
例如真实标签:
#EXTINF:10,Title of the segment => I need "Title of the segment" phrase
#EXTINF:20,Title => I need "Title" phrase
#EXTINF:12 => I need "" phrase
double duration;
std::string title;
boost::spirit::qi::rule<Iterator,std::string()> quoutedString;
quoutedString %= lexeme[+(char_)];
bool r = parse(first,last,("#EXTINF:" >> double_[ref(duration) = _1] >> -(',' >> quoutedString[ref(title) = _1] ) )
);
if (!r || first != last) {
addMinorProblem(stateObj,_("Cannot parse information from #EXTINF tag"));
return false;
}
error: call of overloaded ‘ref(std::__cxx11::string&)’ is ambiguous
("#EXTINF:" >> double_[ref(duration) = _1] >> -(',' >> quoutedString[ref(title) = _1] ) )
请帮帮我。我做错了什么?
解决方法
您过多地使用命名空间。此外,ADL 无论如何都会为 Box 1 : B1,B2,B3
Box 2 :
------------------
Box 1 : B2,B3
Box 2 : B1
------------------
Box 1 : B1,B3
Box 2 : B2
------------------
Box 1 : B3
Box 2 : B1,B2
------------------
Box 1 : B1,B2
Box 2 : B3
------------------
Box 1 : B2
Box 2 : B1,B3
------------------
Box 1 : B1
Box 2 : B2,B3
------------------
Box 1 :
Box 2 : B1,B3
参数引入 std::ref
,除非 std::string
被加括号或命名空间限定。
过度使用 ref
从来都不是一个好主意(参见例如 Why is "using namespace std;" considered bad practice?),在这种情况下,该消息阐明了 using namespace
和 std::ref
之间的混淆(可能还有其他人,但您没有提供完整的信息)。
说不:
boost::phoenix::ref
印刷品
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/optional.hpp>
#include <iomanip>
namespace qi = boost::spirit::qi;
namespace px = boost::phoenix;
#define addMinorProblem(...) do {} while (0)
boost::optional<std::pair<double,std::string>> parse(std::string_view input)
{
using Iterator = std::string_view::const_iterator;
Iterator first = begin(input),last = end(input);
double duration;
std::string title;
boost::spirit::qi::rule<Iterator,std::string()> quoutedString;
quoutedString %= qi::lexeme[+(qi::char_)];
bool r = parse(first,last,("#EXTINF:" >> qi::double_[px::ref(duration) = qi::_1] >>
-(',' >> quoutedString[px::ref(title) = qi::_1])));
if (!r || first != last) {
addMinorProblem(stateObj,_("Cannot parse information from #EXTINF tag"));
return {};
}
return std::make_pair(duration,title);
}
int main()
{
for (std::string const input : {
"#EXTINF:10,Title of the segment",// => I need "Title of the
// segment" phrase
"#EXTINF:20,Title",// => I need "Title" phrase
"#EXTINF:12",// => I need "" phrase
}) {
if (auto result = parse(input)) {
std::cout << "Parsed: (" << result->first << "," << std::quoted(result->second) << ")\n";
} else {
std::cout << "Cannot parse " << std::quoted(input) << "\n";
}
}
}
改进,小事
-
通过一些明智的local using 声明,您可以再次使其“更短”:
Parsed: (10,"Title of the segment") Parsed: (20,"Title") Parsed: (12,"")
我个人觉得这比清晰更模糊(想象自己在代码审查中解释
using namespace qi::labels; using px::ref; bool r = parse(first,("#EXTINF:" >> qi::double_[ref(duration) = _1] >> -(',' >> quoutedString[(ref)(title) = _1])));
?) -
没有语义动作的
(ref)(title)
没有意义 -
operator %=
没有船长是没有意义的(见 Boost spirit skipper issues) -
qi::lexeme[]
[原文如此] 用词不当(目前?)因为它不解析引号 -
为什么不使用自动属性传播来代替痛苦的语义操作?它们只会增加编译时间,正如您所发现的,还会增加开发时间。见Boost Spirit: "Semantic actions are evil"?
-
此外,与其在解析后繁琐地检查
quoutedString
,还不如简单地匹配表达式中的first == last
?
以上所有简化为以下内容:
>> qi::eoi
没有更多的boost::optional<std::pair<double,std::string>> parse(std::string_view input)
{
namespace qi = boost::spirit::qi;
double duration;
std::string title;
if (qi::parse(
begin(input),end(input),//
("#EXTINF:" >> qi::double_ >> -(',' >> +qi::char_) >> qi::eoi),duration,title))
{
return std::make_pair(duration,title);
}
addMinorProblem(stateObj,_("Cannot parse information from #EXTINF tag"));
return {};
}
,语义动作,什么不是。仍在打印:
phoenix
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。