calculator.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // calculator.hpp
  3. //
  4. // Copyright 2008 Eric Niebler. Distributed under the Boost
  5. // Software License, Version 1.0. (See accompanying file
  6. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. #include <boost/proto/core.hpp>
  8. #include <boost/proto/context.hpp>
  9. #include <boost/test/unit_test.hpp>
  10. using namespace boost;
  11. struct placeholder {};
  12. proto::terminal<placeholder>::type const _1 = {{}};
  13. struct calculator : proto::callable_context<calculator const>
  14. {
  15. typedef int result_type;
  16. calculator(int i)
  17. : i_(i)
  18. {}
  19. int operator ()(proto::tag::terminal, placeholder) const
  20. {
  21. return this->i_;
  22. }
  23. int operator ()(proto::tag::terminal, int j) const
  24. {
  25. return j;
  26. }
  27. template<typename Left, typename Right>
  28. int operator ()(proto::tag::plus, Left const &left, Right const &right) const
  29. {
  30. return proto::eval(left, *this) + proto::eval(right, *this);
  31. }
  32. template<typename Left, typename Right>
  33. int operator ()(proto::tag::minus, Left const &left, Right const &right) const
  34. {
  35. return proto::eval(left, *this) - proto::eval(right, *this);
  36. }
  37. template<typename Left, typename Right>
  38. int operator ()(proto::tag::multiplies, Left const &left, Right const &right) const
  39. {
  40. return proto::eval(left, *this) * proto::eval(right, *this);
  41. }
  42. template<typename Left, typename Right>
  43. int operator ()(proto::tag::divides, Left const &left, Right const &right) const
  44. {
  45. return proto::eval(left, *this) / proto::eval(right, *this);
  46. }
  47. private:
  48. int i_;
  49. };
  50. template<typename Fun, typename Expr>
  51. struct functional
  52. {
  53. typedef typename proto::result_of::eval<Expr, Fun>::type result_type;
  54. functional(Expr const &expr)
  55. : expr_(expr)
  56. {}
  57. template<typename T>
  58. result_type operator ()(T const &t) const
  59. {
  60. Fun fun(t);
  61. return proto::eval(this->expr_, fun);
  62. }
  63. private:
  64. Expr const &expr_;
  65. };
  66. template<typename Fun, typename Expr>
  67. functional<Fun, Expr> as(Expr const &expr)
  68. {
  69. return functional<Fun, Expr>(expr);
  70. }
  71. void test_calculator()
  72. {
  73. BOOST_CHECK_EQUAL(10, proto::eval(((_1 + 42)-3)/4, calculator(1)));
  74. BOOST_CHECK_EQUAL(11, proto::eval(((_1 + 42)-3)/4, calculator(5)));
  75. BOOST_CHECK_EQUAL(10, as<calculator>(((_1 + 42)-3)/4)(1));
  76. BOOST_CHECK_EQUAL(11, as<calculator>(((_1 + 42)-3)/4)(5));
  77. }
  78. using namespace unit_test;
  79. ///////////////////////////////////////////////////////////////////////////////
  80. // init_unit_test_suite
  81. //
  82. test_suite* init_unit_test_suite( int argc, char* argv[] )
  83. {
  84. test_suite *test = BOOST_TEST_SUITE("test immediate evaluation of proto parse trees");
  85. test->add(BOOST_TEST_CASE(&test_calculator));
  86. return test;
  87. }