calc2.cpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. //[ Calc2
  2. // Copyright 2008 Eric Niebler. Distributed under the Boost
  3. // Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. //
  6. // This example enhances the simple arithmetic expression evaluator
  7. // in calc1.cpp by using proto::extends to make arithmetic
  8. // expressions immediately evaluable with operator (), a-la a
  9. // function object
  10. #include <iostream>
  11. #include <boost/proto/core.hpp>
  12. #include <boost/proto/context.hpp>
  13. namespace proto = boost::proto;
  14. using proto::_;
  15. template<typename Expr>
  16. struct calculator_expression;
  17. // Tell proto how to generate expressions in the calculator_domain
  18. struct calculator_domain
  19. : proto::domain<proto::generator<calculator_expression> >
  20. {};
  21. // Will be used to define the placeholders _1 and _2
  22. template<int I> struct placeholder {};
  23. // Define a calculator context, for evaluating arithmetic expressions
  24. // (This is as before, in calc1.cpp)
  25. struct calculator_context
  26. : proto::callable_context< calculator_context const >
  27. {
  28. // The values bound to the placeholders
  29. double d[2];
  30. // The result of evaluating arithmetic expressions
  31. typedef double result_type;
  32. explicit calculator_context(double d1 = 0., double d2 = 0.)
  33. {
  34. d[0] = d1;
  35. d[1] = d2;
  36. }
  37. // Handle the evaluation of the placeholder terminals
  38. template<int I>
  39. double operator ()(proto::tag::terminal, placeholder<I>) const
  40. {
  41. return d[ I - 1 ];
  42. }
  43. };
  44. // Wrap all calculator expressions in this type, which defines
  45. // operator () to evaluate the expression.
  46. template<typename Expr>
  47. struct calculator_expression
  48. : proto::extends<Expr, calculator_expression<Expr>, calculator_domain>
  49. {
  50. explicit calculator_expression(Expr const &expr = Expr())
  51. : calculator_expression::proto_extends(expr)
  52. {}
  53. BOOST_PROTO_EXTENDS_USING_ASSIGN(calculator_expression<Expr>)
  54. // Override operator () to evaluate the expression
  55. double operator ()() const
  56. {
  57. calculator_context const ctx;
  58. return proto::eval(*this, ctx);
  59. }
  60. double operator ()(double d1) const
  61. {
  62. calculator_context const ctx(d1);
  63. return proto::eval(*this, ctx);
  64. }
  65. double operator ()(double d1, double d2) const
  66. {
  67. calculator_context const ctx(d1, d2);
  68. return proto::eval(*this, ctx);
  69. }
  70. };
  71. // Define some placeholders (notice they're wrapped in calculator_expression<>)
  72. calculator_expression<proto::terminal< placeholder< 1 > >::type> const _1;
  73. calculator_expression<proto::terminal< placeholder< 2 > >::type> const _2;
  74. // Now, our arithmetic expressions are immediately executable function objects:
  75. int main()
  76. {
  77. // Displays "5"
  78. std::cout << (_1 + 2.0)( 3.0 ) << std::endl;
  79. // Displays "6"
  80. std::cout << ( _1 * _2 )( 3.0, 2.0 ) << std::endl;
  81. // Displays "0.5"
  82. std::cout << ( (_1 - _2) / _2 )( 3.0, 2.0 ) << std::endl;
  83. return 0;
  84. }
  85. //]