When using qi::locals
, a local parameter doesn't seem like it can be used as the semantic predicate to eps
. Here is a stripped down fictional example:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
using namespace qi::labels;
using qi::eps;
template <typename Iterator, typename Any>
struct parser : qi::grammar<Iterator, Any(), qi::locals<bool> > {
parser() : parser::base_type(p) {
p = eps[_a=false] >> eps(_a);
}
qi::rule<Iterator, Any(), qi::locals<bool> > p;
};
int main(int argc, const char *argv[]) {
int val;
std::string data;
auto i = data.cbegin();
auto end = data.cend();
parser<decltype(i), decltype(val) > p;
bool rv = phrase_parse(i, end, p, ascii::blank, val);
return rv ? 0 : 1;
}
In this example, if I remove the (_a)
after the second eps
, everything compiles cleanly. With the (_a)
, I get a morass of failed template instantiation. The context doesn't matter, as I have solved this problem in my real code-base another way, but I would like to know why this does not work.
On my compilers/boost versions it works See also Live On Coliru
On a whim I'm suspecting bugs that have crept into the "old" Phoenix V2 implementation. Phoenix V2 was still a part of the Spirit Library technically. It has been superseded by Phoenix V3 which lives as the separate library in boost/phoenx/...
.
Boost Phoenix V2 is showing cracks of age - mainly on modern compilers where the BOOST_RESULT_OF() utilities use decltype
.
Long story short
try using
#define BOOST_SPIRIT_USE_PHOENIX_V3
to use it iff your compiler/boost combination doesn't select it.¹
inversely, if your compiler is oldish, try
#define BOOST_RESULT_OF_USE_TR1
¹ Recent Spirit versions dropped Phoenix V2 : Farewell Phoenix-v2