实际上,自1.62以来,recursive\u包装器更多地限制了隐式构造的选项:
Wandbox on Boost 1.61
boost::variant<int, boost::recursive_wrapper<std::string> > x;
x = "worked before";
std::cout << boost::get<std::string>(x) << "\n";
Broken on Boost 1.62
boost::变量(<int,boost::recursive\u包装器<标准::字符串(>)&燃气轮机;x;
x=“以前工作过”;
标准::cout<&书信电报;boost::获取(<标准::字符串(>);(x) <&书信电报;“\n”;
在这种情况下,很容易修复:
Fixed on Boost 1.62
x = std::string("Hello world");
您的代码
在代码中,递归包装器的嵌套使用使事情变得复杂。好消息是,您不需要有两层。只需放下一个:
typedef boost::variant<
int,
computationExpr
> expr;
实例化已经被第二个递归包装器充分解耦。现在,一切又好了。
演示时间
请注意一些样式修复/建议:
此外,我对
expr
变量,因为它们在默认构造上触发无限递归。
Live On Coliru
#pragma once
#include <string>
#include <boost/variant.hpp>
struct AccTag {};
template <typename> struct unop;
typedef unop<AccTag> Acc;
typedef boost::variant<
boost::recursive_wrapper<Acc>
> computationExpr;
typedef boost::variant<
int,
computationExpr
> expr;
template <typename> struct unop {
unop() : oper1() { }
explicit unop(const expr& o) : oper1(o) { }
expr oper1;
};
expr parse(const std::string& expression, bool& ok);
#include "Parser.h"
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
namespace qi = boost::spirit::qi;
template <typename Iterator = std::string::const_iterator, typename Skipper = qi::space_type>
class ParserImpl : public qi::grammar<Iterator, expr(), Skipper>
{
public:
ParserImpl() : ParserImpl::base_type(expr_)
{
namespace phx = boost::phoenix;
using namespace qi;
expr_ = props_.alias();
props_ =
(lit("Acc") >> '(' >> int_ >> ')')[_val = phx::construct<Acc>(_1)]
;
}
private:
qi::rule<Iterator, expr(), Skipper> props_;
qi::rule<Iterator, expr(), Skipper> expr_;
};
expr parse(const std::string& formula, bool& ok)
{
expr result;
ParserImpl<> parser;
auto b = formula.begin();
auto e = formula.end();
ok = qi::phrase_parse(b, e, parser >> qi::eoi, qi::space, result);
return result;
}
static inline std::ostream& operator<<(std::ostream& os, Acc const& o) {
return os << "Acc(" << o.oper1 << ")";
}
int main() {
bool ok;
auto e = parse("Acc (3)", ok);
if (ok)
std::cout << "Parsed: " << e << "\n";
else
std::cout << "Parse failed\n";
}
印刷品
Parsed: Acc(3)