2016-03-09 80 views
0

我有binop結構,它表示2個相同類型表達式的二進制運算。 我有兩種不同類型的表達式:arithmetic_exprlogical_expr定義爲boost :: variant。Boost recursive_wrapper遞歸

目標是讓binop有兩個字段:rhslhs這些表達式的具體類型。如何實現這一目標?

這是我想出了迄今:

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

我們可以通過定義的地方開始arithmetic_expr。我在上面的代碼中看不到它的定義。 –

+0

如果我轉發declare arithmetic_expr作爲一個結構體,編譯器會抱怨變體聲明與結構體不兼容。 – 0xFF

+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 
+0

這很好,但是說我有'使用bool_expression = boost :: variant >'。如何將'binary_op.expression'模板化爲'bool_expression'?這就是問題 – 0xFF

+0

您需要添加包含bool_expression和int_expression的另一種變體類型。您可能還需要轉換功能來在它們之間進行轉換。基本上你正在建立一個EBNF,所以你需要一個變量來處理每個複合詞。祝你好運! :) –

+0

沒錯,已經嘗試過了,但我想避免2個表達式的包裝變體..不知道這是可能的 – 0xFF