1 //[ Calc1
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 is a simple example of how to build an arithmetic expression
7 // evaluator with placeholders.
8 
9 #include <iostream>
10 #include <boost/proto/core.hpp>
11 #include <boost/proto/context.hpp>
12 namespace proto = boost::proto;
13 using proto::_;
14 
15 template<int I> struct placeholder {};
16 
17 // Define some placeholders
18 proto::terminal< placeholder< 1 > >::type const _1 = {{}};
19 proto::terminal< placeholder< 2 > >::type const _2 = {{}};
20 
21 // Define a calculator context, for evaluating arithmetic expressions
22 struct calculator_context
23   : proto::callable_context< calculator_context const >
24 {
25     // The values bound to the placeholders
26     double d[2];
27 
28     // The result of evaluating arithmetic expressions
29     typedef double result_type;
30 
calculator_contextcalculator_context31     explicit calculator_context(double d1 = 0., double d2 = 0.)
32     {
33         d[0] = d1;
34         d[1] = d2;
35     }
36 
37     // Handle the evaluation of the placeholder terminals
38     template<int I>
operator ()calculator_context39     double operator ()(proto::tag::terminal, placeholder<I>) const
40     {
41         return d[ I - 1 ];
42     }
43 };
44 
45 template<typename Expr>
evaluate(Expr const & expr,double d1=0.,double d2=0.)46 double evaluate( Expr const &expr, double d1 = 0., double d2 = 0. )
47 {
48     // Create a calculator context with d1 and d2 substituted for _1 and _2
49     calculator_context const ctx(d1, d2);
50 
51     // Evaluate the calculator expression with the calculator_context
52     return proto::eval(expr, ctx);
53 }
54 
main()55 int main()
56 {
57     // Displays "5"
58     std::cout << evaluate( _1 + 2.0, 3.0 ) << std::endl;
59 
60     // Displays "6"
61     std::cout << evaluate( _1 * _2, 3.0, 2.0 ) << std::endl;
62 
63     // Displays "0.5"
64     std::cout << evaluate( (_1 - _2) / _2, 3.0, 2.0 ) << std::endl;
65 
66     return 0;
67 }
68 //]
69