boost :: spirit :: qi :: phrase_parse中某处未定义的行为

时间:2014-10-16 17:33:14

标签: c++ boost auto boost-spirit

我正在学习使用boost :: spirit库。我拿了这个例子http://www.boost.org/doc/libs/1_56_0/libs/spirit/example/qi/num_list1.cpp并在我的电脑上编译它 - 它工作正常。

但是,如果我稍微修改它 - 如果我初始化解析器本身

auto parser = qi::double_ >> *(',' >> qi::double_);

作为全局变量并将其传递给phrase_parse,一切都变得疯狂。这是完整的修改代码(只修改了1行,添加了1行) - http://pastebin.com/5rWS3pMt

如果我运行原始代码并通过" 3.14,3.15"对于stdin,它说Parsing成功了,但是我的修改版本失败了。我尝试了很多相同类型的修改 - 将解析器分配给全局变量 - 在某些编译器的某些变体中它是段错误的。

我不明白为什么以及如何如此。 这是另一个更简单的版本,它在clang ++上打印true,然后是段错误,在g ++上只是段错误

#include <boost/spirit/include/qi.hpp>

#include <iostream>
#include <string>

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

const auto doubles_parser_global = qi::double_ >> *(',' >> qi::double_);

int main() {
    const auto doubles_parser_local = qi::double_ >> *(',' >> qi::double_);

    const std::string nums {"3.14, 3.15, 3.1415926"};

    std::cout << std::boolalpha;

    std::cout
        << qi::phrase_parse(
            nums.cbegin(), nums.cend(), doubles_parser_local, ascii::space
        )
        << std::endl;                             // works fine

    std::cout
        << qi::phrase_parse(
            nums.cbegin(), nums.cend(), doubles_parser_global, ascii::space
        )                                         // this segfaults
        << std::endl;
}

1 个答案:

答案 0 :(得分:2)

您不能将auto用于存储解析器表达式¹

您需要直接从临时表达式进行评估,或者需要分配规则/语法:

const qi::rule<std::string::const_iterator, qi::space_type> doubles_parser_local = qi::double_ >> *(',' >> qi::double_);

你可以在最近的BOost版本(可能是开发分支)上吃蛋糕并吃它也应该有一个BOOST_SPIRIT_AUTO宏

这已成为一个常见问题项目:

¹我认为这实际上是对底层Proto库的限制。在github上有一个Proto-0x lib版本(由Eric Niebler提供),它承诺通过完全重新设计以了解引用来解决这些问题。我认为这需要一些Boost Proto目前无法使用的c ++ 11功能。