问题
Are spirit parsers not meant to be used with auto?
A simple parser works fine when passed to qi::parse() inline, but crashes with segfault if passed via an auto variable:
#include <cstdio>
#include <string>
#include <boost/spirit/include/qi.hpp>
using namespace std;
namespace qi = boost::spirit::qi;
int main()
{
string line = "[z]";
auto bracketed_z = '[' >> +qi::char_('z') >> ']';
auto p = line.cbegin();
printf("%d", qi::parse(p, line.cend(), '[' >> +qi::char_('z') >> ']')); // Works
p = line.cbegin();
printf("%d", qi::parse(p, line.cend(), bracketed_z)); // Crashes
}
Reproes with g++-4.8 and VC13.
Update: an error was fixed in the original code (p was not re-initialized before the second call to parse()).
回答1:
Spirit Parsers are not designed to be used with auto in Spirit V2.
This is because the underlying Proto expression templates hold references to the temporaries.
You can use
qi::copy()(existing in the trunk after boost_1_55_0, not in any released version at this time)boost::proto::deep_copy- or BOOST_SPIRIT_AUTO (first coined here)
I've written about these things more often on SO: https://stackoverflow.com/search?q=user%3A85371+deep_copy, specifically, this:
- boost spirit V2 qi bug associated with optimization level
Boost Spirit X3 will not have this limitation.
回答2:
Boost.Spirit uses expression templates and does not work with auto. A workaround is to use boost::proto::deep_copy:
auto bracketed_z = proto::deep_copy('[' >> +qi::char_('z') >> ']');
来源:https://stackoverflow.com/questions/22023779/assigning-parsers-to-auto-variables