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 #include <boost/yap/expression.hpp>
7 
8 #include <boost/mpl/assert.hpp>
9 
10 #include <boost/test/minimal.hpp>
11 
12 
13 template<typename T>
14 using term = boost::yap::terminal<boost::yap::expression, T>;
15 
16 template<typename T>
17 using ref = boost::yap::expression_ref<boost::yap::expression, T>;
18 
19 namespace yap = boost::yap;
20 namespace bh = boost::hana;
21 
22 
23 template<boost::yap::expr_kind Kind, typename Tuple>
24 struct user_expr
25 {
26     static boost::yap::expr_kind const kind = Kind;
27 
28     Tuple elements;
29 };
30 
31 BOOST_YAP_USER_BINARY_OPERATOR(plus, user_expr, user_expr)
32 
33 template<typename T>
34 using user_term = boost::yap::terminal<user_expr, T>;
35 
36 template<typename T>
37 using user_ref = boost::yap::expression_ref<user_expr, T>;
38 
39 
test_main(int,char * [])40 int test_main(int, char * [])
41 {
42     {
43         {
44             BOOST_MPL_ASSERT((std::is_same<decltype(yap::value(1.0)), double &&>));
45             BOOST_CHECK(yap::value(1.0) == 1.0);
46         }
47 
48         {
49             double d = 2.0;
50             BOOST_MPL_ASSERT((std::is_same<decltype(yap::value(d)), double &>));
51             BOOST_CHECK(yap::value(d) == 2.0);
52         }
53 
54         {
55             double const d = 3.0;
56             BOOST_MPL_ASSERT(
57                 (std::is_same<decltype(yap::value(d)), double const &>));
58             BOOST_CHECK(yap::value(d) == 3.0);
59         }
60     }
61 
62     {
63         {
64             term<double> td = {{1.0}};
65             BOOST_MPL_ASSERT(
66                 (std::is_same<decltype(yap::value(std::move(td))), double &&>));
67             BOOST_CHECK(yap::value(std::move(td)) == 1.0);
68         }
69 
70         {
71             term<double> td = {{2.0}};
72             BOOST_MPL_ASSERT((std::is_same<decltype(yap::value(td)), double &>));
73             BOOST_CHECK(yap::value(td) == 2.0);
74         }
75 
76         {
77             term<double> const td = {{3.0}};
78             BOOST_MPL_ASSERT(
79                 (std::is_same<decltype(yap::value(td)), double const &>));
80             BOOST_CHECK(yap::value(td) == 3.0);
81         }
82 
83         term<double> unity = {{1.0}};
84         using plus_expr_type = yap::expression<
85             yap::expr_kind::plus,
86             bh::tuple<ref<term<double> &>, term<int>>>;
87         plus_expr_type plus_expr = unity + term<int>{{1}};
88 
89         {
90             ref<term<double> &> ref = bh::front(plus_expr.elements);
91             BOOST_MPL_ASSERT(
92                 (std::is_same<decltype(yap::value(std::move(ref))), double &>));
93         }
94 
95         {
96             ref<term<double> &> ref = bh::front(plus_expr.elements);
97             BOOST_MPL_ASSERT((std::is_same<decltype(yap::value(ref)), double &>));
98         }
99 
100         {
101             ref<term<double> &> const ref = bh::front(plus_expr.elements);
102             BOOST_MPL_ASSERT((std::is_same<decltype(yap::value(ref)), double &>));
103         }
104 
105         {
106             term<double> const unity = {{1.0}};
107             yap::expression<
108                 yap::expr_kind::plus,
109                 bh::tuple<ref<term<double> const &>, term<int>>>
110                 plus_expr = unity + term<int>{{1}};
111 
112             {
113                 ref<term<double> const &> ref = bh::front(plus_expr.elements);
114                 BOOST_MPL_ASSERT((std::is_same<
115                                   decltype(yap::value(std::move(ref))),
116                                   double const &>));
117             }
118 
119             {
120                 ref<term<double> const &> ref = bh::front(plus_expr.elements);
121                 BOOST_MPL_ASSERT(
122                     (std::is_same<decltype(yap::value(ref)), double const &>));
123             }
124 
125             {
126                 ref<term<double> const &> const ref = bh::front(plus_expr.elements);
127                 BOOST_MPL_ASSERT(
128                     (std::is_same<decltype(yap::value(ref)), double const &>));
129             }
130         }
131     }
132 
133     {
134         {
135             user_term<double> td = {{1.0}};
136             BOOST_MPL_ASSERT(
137                 (std::is_same<decltype(yap::value(std::move(td))), double &&>));
138             BOOST_CHECK(yap::value(std::move(td)) == 1.0);
139         }
140 
141         {
142             user_term<double> td = {{2.0}};
143             BOOST_MPL_ASSERT((std::is_same<decltype(yap::value(td)), double &>));
144             BOOST_CHECK(yap::value(td) == 2.0);
145         }
146 
147         {
148             user_term<double> const td = {{3.0}};
149             BOOST_MPL_ASSERT(
150                 (std::is_same<decltype(yap::value(td)), double const &>));
151             BOOST_CHECK(yap::value(td) == 3.0);
152         }
153 
154         user_term<double> unity = {{1.0}};
155         using plus_expr_type = user_expr<
156             yap::expr_kind::plus,
157             bh::tuple<user_ref<user_term<double> &>, user_term<int>>>;
158         plus_expr_type plus_expr = unity + user_term<int>{{1}};
159 
160         {
161             user_ref<user_term<double> &> ref = bh::front(plus_expr.elements);
162             BOOST_MPL_ASSERT(
163                 (std::is_same<decltype(yap::value(std::move(ref))), double &>));
164         }
165 
166         {
167             user_ref<user_term<double> &> ref = bh::front(plus_expr.elements);
168             BOOST_MPL_ASSERT((std::is_same<decltype(yap::value(ref)), double &>));
169         }
170 
171         {
172             user_ref<user_term<double> &> const ref = bh::front(plus_expr.elements);
173             BOOST_MPL_ASSERT((std::is_same<decltype(yap::value(ref)), double &>));
174         }
175 
176         {
177             user_term<double> const unity = {{1.0}};
178             user_expr<
179                 yap::expr_kind::plus,
180                 bh::tuple<user_ref<user_term<double> const &>, user_term<int>>>
181                 plus_expr = unity + user_term<int>{{1}};
182 
183             {
184                 user_ref<user_term<double> const &> ref =
185                     bh::front(plus_expr.elements);
186                 BOOST_MPL_ASSERT((std::is_same<
187                                   decltype(yap::value(std::move(ref))),
188                                   double const &>));
189             }
190 
191             {
192                 user_ref<user_term<double> const &> ref =
193                     bh::front(plus_expr.elements);
194                 BOOST_MPL_ASSERT(
195                     (std::is_same<decltype(yap::value(ref)), double const &>));
196             }
197 
198             {
199                 user_ref<user_term<double> const &> const ref =
200                     bh::front(plus_expr.elements);
201                 BOOST_MPL_ASSERT(
202                     (std::is_same<decltype(yap::value(ref)), double const &>));
203             }
204         }
205     }
206 
207     return 0;
208 }
209