Guest User

Untitled

a guest
Jun 24th, 2018
180
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.51 KB | None | 0 0
  1. /*
  2. * test for Boost.Variant
  3. *
  4. * This sample needs recursive evaluations to execute, therefore there is a
  5. * stack overflow risk.
  6. *
  7. * written by janus_wel<janus.wel.3@gmail.com>
  8. * This source code is in public domain, and has NO WARRANTY.
  9. * */
  10.  
  11. #include <iostream>
  12. #include <boost/variant.hpp>
  13.  
  14. namespace four_arithmetic_ops {
  15. // definitions of four arithmetic operations
  16. struct add { static char symbol(void) { return '+'; } };
  17. struct sub { static char symbol(void) { return '-'; } };
  18. struct mul { static char symbol(void) { return '*'; } };
  19. struct div { static char symbol(void) { return '/'; } };
  20.  
  21. // definitions of data structure
  22. // syntax tree by using binary tree
  23. template <typename Op> struct binary_op;
  24.  
  25. typedef boost::variant<
  26. double,
  27. boost::recursive_wrapper<binary_op<add> >,
  28. boost::recursive_wrapper<binary_op<sub> >,
  29. boost::recursive_wrapper<binary_op<mul> >,
  30. boost::recursive_wrapper<binary_op<div> >
  31. > expr;
  32.  
  33. template <typename Op>
  34. struct binary_op {
  35. expr left;
  36. expr right;
  37.  
  38. binary_op(const expr& lhs, const expr& rhs)
  39. : left(lhs), right(rhs) {}
  40. };
  41.  
  42. // for convenience
  43. typedef binary_op<add> op_add;
  44. typedef binary_op<sub> op_sub;
  45. typedef binary_op<mul> op_mul;
  46. typedef binary_op<div> op_div;
  47.  
  48. // evaluate data structure recursively
  49. struct evaluator : public boost::static_visitor<double> {
  50. double operator()(const double& value) const {
  51. return value;
  52. }
  53.  
  54. double operator()(const op_add& i) const {
  55. return
  56. boost::apply_visitor(evaluator(), i.left)
  57. + boost::apply_visitor(evaluator(), i.right);
  58. }
  59.  
  60. double operator()(const op_sub& i) const {
  61. return
  62. boost::apply_visitor(evaluator(), i.left)
  63. - boost::apply_visitor(evaluator(), i.right);
  64. }
  65.  
  66. double operator()(const op_mul& i) const {
  67. return
  68. boost::apply_visitor(evaluator(), i.left)
  69. * boost::apply_visitor(evaluator(), i.right);
  70. }
  71.  
  72. double operator()(const op_div& i) const {
  73. return
  74. boost::apply_visitor(evaluator(), i.left)
  75. / boost::apply_visitor(evaluator(), i.right);
  76. }
  77. };
  78.  
  79. // for print
  80. template<typename Op>
  81. std::ostream& operator<<(std::ostream& out, const binary_op<Op>& b) {
  82. return out
  83. << '(' << b.left << ' '
  84. << Op::symbol()
  85. << ' ' << b.right << ')';
  86. }
  87.  
  88. // for convenience
  89. inline double calc(const expr& e) {
  90. return boost::apply_visitor(evaluator(), e);
  91. }
  92.  
  93. // for convenience, but these are over the top...
  94. op_add operator+(const expr& a, const expr& b) {
  95. return op_add(a, b);
  96. }
  97. op_sub operator-(const expr& a, const expr& b) {
  98. return op_sub(a, b);
  99. }
  100. op_mul operator*(const expr& a, const expr& b) {
  101. return op_mul(a, b);
  102. }
  103. op_div operator/(const expr& a, const expr& b) {
  104. return op_div(a, b);
  105. }
  106. }
  107.  
  108. int main(void) {
  109. using namespace four_arithmetic_ops;
  110.  
  111. /*
  112. * This is equivalent to below expressions
  113. * expr e((expr(9) / expr(3)) * (expr(7) - expr(2)) + expr(8));
  114. * */
  115. expr e(
  116. op_add(
  117. op_mul(
  118. op_div(9, 3),
  119. op_sub(7, 2)),
  120. 8));
  121. std::cout
  122. << e << " = " << calc(e)
  123. << std::endl;
  124. return 0;
  125. }
Add Comment
Please, Sign In to add comment