Assigning parsers to auto variables

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()).


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.


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') >> ']');