我想要用于工作项目的语法。最低可执行示例是:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#pragma GCC diagnostic ignored "-Wunused-variable"
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/qi_grammar.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#pragma GCC diagnostic pop // pops
#include <iostream>
int main()
{
typedef unsigned long long ull;
std::string curline = "1;2;;3,4;5";
std::cout << "parsing: " << curline << "\n";
namespace qi = boost::spirit::qi;
auto ids = -qi::ulong_long % ','; // '-' allows for empty vecs.
auto match_type_res = ids % ';' ;
std::vector<std::vector<ull> > r;
qi::parse(curline.begin(), curline.end(), match_type_res, r);
std::cout << "got: ";
for (auto v: r){
for (auto i : v)
std::cout << i << ",";
std::cout << ";";
}
std::cout <<"\n";
}
在我的个人计算机上,这会产生正确的输出: 解析:1; 2 ;; 3,4; 5 得到:1,; 2,;; 3,4 ,; 5 ,;
但在工作中它产生: 解析:1; 2 ;; 3,4; 5 得到:1,; 2,;; 3,
换句话说,只要有一个以上的元素,它就无法解析长整数的向量。
现在,我已经确定工作系统正在使用boost 1.56,而我的私人计算机正在使用1.57。这是原因吗?
知道我们在堆栈溢出方面有一些真正的精神专家,我希望有人可能知道这个问题的来源,或者至少可以缩小我需要检查的事情的数量。
如果升级版本出现问题,我可能会说服公司进行升级,但无论如何都会欢迎解决方法。
答案 0 :(得分:2)
您在代码中调用Undefined Behaviour。
特别是在您使用auto
存储解析器表达式的位置。 Expression Template包含对包含完整表达式¹末尾dangling的临时对象的引用。
UB暗示任何事情都可能发生。两个编译器都是对的!最好的部分是,根据使用的编译器标志,您可能会看到不同的行为。
使用以下方法修复:
qi::copy
(或boost::proto::deep_copy
v.1.55 IIRC)BOOST_SPIRIT_AUTO
代替BOOST_AUTO
(如果您也支持C ++ 03,则非常有帮助)使用qi::rule<>
和qi::grammar<>
(non-terminals)进行类型擦除和表达式。这也会对性能产生影响,但也会提供更多功能,例如
lexeme[]
(见here)另请注意,Spirit X3承诺放弃使用auto的限制。由于使用了c ++ 14特性,它基本上更加轻巧。请记住,它还不稳定。
显示带有-O2的GCC显示未定义的结果;的 Live On Coliru 强>
固定版本:
<强> Live On Coliru 强>
//#pragma GCC diagnostic push
//#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
//#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
//#pragma GCC diagnostic ignored "-Wunused-variable"
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/qi.hpp>
//#pragma GCC diagnostic pop // pops
#include <iostream>
int main() {
typedef unsigned long long ull;
std::string const curline = "1;2;;3,4;5";
std::cout << "parsing: '" << curline << "'\n";
namespace qi = boost::spirit::qi;
#if 0 // THIS IS UNDEFINED BEHAVIOUR:
auto ids = -qi::ulong_long % ','; // '-' allows for empty vecs.
auto grammar = ids % ';';
#else // THIS IS CORRECT:
auto ids = qi::copy(-qi::ulong_long % ','); // '-' allows for empty vecs.
auto grammar = qi::copy(ids % ';');
#endif
std::vector<std::vector<ull> > r;
qi::parse(curline.begin(), curline.end(), grammar, r);
std::cout << "got: ";
for (auto v: r){
for (auto i : v)
std::cout << i << ",";
std::cout << ";";
}
std::cout <<"\n";
}
打印(也使用GCC -O2!):
parsing: '1;2;;3,4;5'
got: 1,;2,;;3,4,;5,;
¹(这里基本上是“在下一个分号”;但在标准中)