我有binop
结构,表示相同类型的2个表达式的二进制运算。
我有两种不同类型的表达式:arithmetic_expr
和logical_expr
定义为boost :: variant。
目标是让binop
有两个字段:rhs
和lhs
这些表达式的具体类型。怎么做到这一点?
这是我到目前为止所提出的:
template <typename expr_type, typename tag> struct binop;
struct op_plus {};
typedef boost::variant<
int,
boost::recursive_wrapper<binop<arithmetic_expr, op_plus>> // <-- fails here 'arithmetic_expr': undeclared identifier
> arithmetic_expr;
struct op_and {};
typedef boost::variant<
bool,
boost::recursive_wrapper<binop<logical_expr, op_and>>
> logical_expr;
template <typename expr_type, typename tag>
struct binop
{
explicit binop(const expr_type& l, const expr_type& r) : lhs(l), rhs(r) { }
expr_type lhs, rhs;
};
用例示例如下:
(((1 + 2) /* arithmetic_expr */ + 3) /* arithmetic_expr */ AND (4 + 5) /* arithmetic_expr */) /* logical_expr */
答案 0 :(得分:1)
这样的事情?
#include <iostream>
#include <utility>
#include <boost/variant.hpp>
// identity evaluation
int evaluate(int i) { return i; }
// introduce the concep of binary op
template<class ActualOp> struct binary_op;
using add = binary_op<std::plus<int>>;
using subtract = binary_op<std::minus<int>>;
using times = binary_op<std::multiplies<int>>;
// our variant
using expression = boost::variant
<
int,
boost::recursive_wrapper<add>,
boost::recursive_wrapper<subtract>,
boost::recursive_wrapper<times>
>;
// overload for evaluating the variant
struct compute : boost::static_visitor<int>
{
template<class T> int operator()(const T& t) const { return evaluate(t); }
};
int evaluate(const expression& e)
{
return boost::apply_visitor(compute(), e);
};
// evaluate the binary op
template<class ActualOp>
struct binary_op
{
binary_op(expression l, expression r)
: _l(std::move(l)), _r(std::move(r))
{}
ActualOp _op;
expression _l, _r;
};
template<class Op>
int evaluate(const binary_op<Op>& o) {
return o._op(evaluate(o._l), evaluate(o._r));
}
int main()
{
using namespace std;
expression e = add(6, times(3,subtract(7,2)));
cout << evaluate(e) << endl;
return 0;
}
预期产出:
21