• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
11 #include <iostream>
12 #include <boost/proto/core.hpp>
13 #include <boost/proto/context.hpp>
14 namespace proto = boost::proto;
15 using proto::_;
16 
17 template<typename Expr>
18 struct calculator_expression;
19 
20 // Tell proto how to generate expressions in the calculator_domain
21 struct calculator_domain
22   : proto::domain<proto::generator<calculator_expression> >
23 {};
24 
25 // Will be used to define the placeholders _1 and _2
26 template<int I> struct placeholder {};
27 
28 // Define a calculator context, for evaluating arithmetic expressions
29 // (This is as before, in calc1.cpp)
30 struct calculator_context
31   : proto::callable_context< calculator_context const >
32 {
33     // The values bound to the placeholders
34     double d[2];
35 
36     // The result of evaluating arithmetic expressions
37     typedef double result_type;
38 
calculator_contextcalculator_context39     explicit calculator_context(double d1 = 0., double d2 = 0.)
40     {
41         d[0] = d1;
42         d[1] = d2;
43     }
44 
45     // Handle the evaluation of the placeholder terminals
46     template<int I>
operator ()calculator_context47     double operator ()(proto::tag::terminal, placeholder<I>) const
48     {
49         return d[ I - 1 ];
50     }
51 };
52 
53 // Wrap all calculator expressions in this type, which defines
54 // operator () to evaluate the expression.
55 template<typename Expr>
56 struct calculator_expression
57   : proto::extends<Expr, calculator_expression<Expr>, calculator_domain>
58 {
calculator_expressioncalculator_expression59     explicit calculator_expression(Expr const &expr = Expr())
60       : calculator_expression::proto_extends(expr)
61     {}
62 
BOOST_PROTO_EXTENDS_USING_ASSIGNcalculator_expression63     BOOST_PROTO_EXTENDS_USING_ASSIGN(calculator_expression<Expr>)
64 
65     // Override operator () to evaluate the expression
66     double operator ()() const
67     {
68         calculator_context const ctx;
69         return proto::eval(*this, ctx);
70     }
71 
operator ()calculator_expression72     double operator ()(double d1) const
73     {
74         calculator_context const ctx(d1);
75         return proto::eval(*this, ctx);
76     }
77 
operator ()calculator_expression78     double operator ()(double d1, double d2) const
79     {
80         calculator_context const ctx(d1, d2);
81         return proto::eval(*this, ctx);
82     }
83 };
84 
85 // Define some placeholders (notice they're wrapped in calculator_expression<>)
86 calculator_expression<proto::terminal< placeholder< 1 > >::type> const _1;
87 calculator_expression<proto::terminal< placeholder< 2 > >::type> const _2;
88 
89 // Now, our arithmetic expressions are immediately executable function objects:
main()90 int main()
91 {
92     // Displays "5"
93     std::cout << (_1 + 2.0)( 3.0 ) << std::endl;
94 
95     // Displays "6"
96     std::cout << ( _1 * _2 )( 3.0, 2.0 ) << std::endl;
97 
98     // Displays "0.5"
99     std::cout << ( (_1 - _2) / _2 )( 3.0, 2.0 ) << std::endl;
100 
101     return 0;
102 }
103 //]
104