• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2016-2018 T. Zachary Laine
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See
4 // accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 //[ calc3
7 #include <boost/yap/expression.hpp>
8 
9 #include <boost/hana/maximum.hpp>
10 
11 #include <iostream>
12 
13 
14 // Look! A transform!  This one transforms the expression tree into the arity
15 // of the expression, based on its placeholders.
16 //[ calc3_get_arity_xform
17 struct get_arity
18 {
19     // Base case 1: Match a placeholder terminal, and return its arity as the
20     // result.
21     template <long long I>
operator ()get_arity22     boost::hana::llong<I> operator() (boost::yap::expr_tag<boost::yap::expr_kind::terminal>,
23                                       boost::yap::placeholder<I>)
24     { return boost::hana::llong_c<I>; }
25 
26     // Base case 2: Match any other terminal.  Return 0; non-placeholders do
27     // not contribute to arity.
28     template <typename T>
operator ()get_arity29     auto operator() (boost::yap::expr_tag<boost::yap::expr_kind::terminal>, T &&)
30     {
31         using namespace boost::hana::literals;
32         return 0_c;
33     }
34 
35     // Recursive case: Match any expression not covered above, and return the
36     // maximum of its children's arities.
37     template <boost::yap::expr_kind Kind, typename... Arg>
operator ()get_arity38     auto operator() (boost::yap::expr_tag<Kind>, Arg &&... arg)
39     {
40         return boost::hana::maximum(
41             boost::hana::make_tuple(
42                 boost::yap::transform(
43                     boost::yap::as_expr(std::forward<Arg>(arg)),
44                     get_arity{}
45                 )...
46             )
47         );
48     }
49 };
50 //]
51 
main()52 int main ()
53 {
54     using namespace boost::yap::literals;
55 
56     // These lambdas wrap our expressions as callables, and allow us to check
57     // the arity of each as we call it.
58 
59     auto expr_1 = 1_p + 2.0;
60 
61     auto expr_1_fn = [expr_1](auto &&... args) {
62         auto const arity = boost::yap::transform(expr_1, get_arity{});
63         static_assert(arity.value == sizeof...(args), "Called with wrong number of args.");
64         return evaluate(expr_1, args...);
65     };
66 
67     auto expr_2 = 1_p * 2_p;
68 
69     auto expr_2_fn = [expr_2](auto &&... args) {
70         auto const arity = boost::yap::transform(expr_2, get_arity{});
71         static_assert(arity.value == sizeof...(args), "Called with wrong number of args.");
72         return evaluate(expr_2, args...);
73     };
74 
75     auto expr_3 = (1_p - 2_p) / 2_p;
76 
77     auto expr_3_fn = [expr_3](auto &&... args) {
78         auto const arity = boost::yap::transform(expr_3, get_arity{});
79         static_assert(arity.value == sizeof...(args), "Called with wrong number of args.");
80         return evaluate(expr_3, args...);
81     };
82 
83     // Displays "5"
84     std::cout << expr_1_fn(3.0) << std::endl;
85 
86     // Displays "6"
87     std::cout << expr_2_fn(3.0, 2.0) << std::endl;
88 
89     // Displays "0.5"
90     std::cout << expr_3_fn(3.0, 2.0) << std::endl;
91 
92     // Static-asserts with "Called with wrong number of args."
93     //std::cout << expr_3_fn(3.0) << std::endl;
94 
95     // Static-asserts with "Called with wrong number of args."
96     //std::cout << expr_3_fn(3.0, 2.0, 1.0) << std::endl;
97 
98     return 0;
99 }
100 //]
101