I switched my Boost version from 1.6.1 to >=1.6.2 and my boost::spirit
parser code fails to compile. Actually, I thinking the problem has something to do with a bug fix in Boost Variant from version 1.6.1 to version 1.6.2.
Release notes of version 1.6.2 say:
Variant constructors and assignment operators now do not participate in overload resolutions if variant can not hold the input type #5871, #11602
Here is a stripped version of my failing code:
Parser.h
#pragma once
#include <string>
#include <boost/variant.hpp>
struct AccTag {};
template <typename tag> struct unop;
typedef unop<AccTag> Acc;
typedef boost::variant<
boost::recursive_wrapper<Acc>
> computationExpr;
typedef boost::variant<
boost::recursive_wrapper<computationExpr>,
int
> expr;
template <typename tag> struct unop
{
unop() : oper1() {
}
explicit unop(const expr& o) : oper1(o) { }
expr oper1;
};
expr parse(const std::string& expression, bool& ok);
Parser.cpp
#include "Parser.h"
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
using namespace boost;
template <typename Iterator = std::string::iterator, typename Skipper = spirit::qi::space_type>
class ParserImpl : public spirit::qi::grammar<Iterator, expr(), Skipper>
{
public:
ParserImpl() : ParserImpl::base_type(expr_)
{
using namespace boost::spirit::qi;
using namespace boost::phoenix;
expr_ = props_.alias();
props_ = (
(lit("Acc") >> "(" >> int_ >> ")")[_val = construct<Acc>(_1) /* Most likely the source of the error */]
);
}
spirit::qi::rule<Iterator, expr(), Skipper> props_;
spirit::qi::rule<Iterator, expr(), Skipper> expr_;
};
expr parse(const std::string& expression, bool& ok)
{
expr result;
std::string formula = expression;
ParserImpl<> parser;
auto b = formula.begin();
auto e = formula.end();
ok = spirit::qi::phrase_parse(b, e, parser, spirit::qi::space, result);
if (b != e) {
ok = false;
}
return result;
}
The code compiles without problems in Version 1.6.1, but fails in Version 1.6.2 with the error:
.../proto/transform/default.hpp(154): error C2679: Binary operator "=": ...
I guess in Version 1.6.1 there was an implicit conversion from computationExpr
to expr
, which is no longer allowed.
How can I fix this code? I think something in _val = construct<Acc>(_1)
must be changed, but I'm lacking the skills to do it.
Indeed, the recursive_wrapper restricts the options for implicit construction more since 1.62:
Wandbox on Boost 1.61
Broken on Boost 1.62
In this case, it's easy to fix: Fixed on Boost 1.62
Your Code
In your code the nested use of recursive wrappers complicates things. The good news is, you don't need to have two layers. Just drop one:
The instantiation is already sufficiently decoupled by the second recursive wrapper. Now, everything is fine again.
Demo Time
Note some style fixes/suggestions:
Live On Coliru
Prints