]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
2 | Copyright (C) 2015 Kohei Takahshi | |
3 | ||
4 | Distributed under the Boost Software License, Version 1.0. (See accompanying | |
5 | file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | ==============================================================================*/ | |
7 | ||
8 | #include <utility> | |
9 | #include <boost/config.hpp> | |
10 | #include <boost/fusion/include/adapt_struct.hpp> | |
11 | #include <boost/fusion/include/as_deque.hpp> | |
12 | #include <boost/fusion/include/as_list.hpp> | |
13 | #include <boost/fusion/include/as_vector.hpp> | |
14 | #include <boost/fusion/include/begin.hpp> | |
15 | #include <boost/fusion/include/is_sequence.hpp> | |
16 | #include <boost/fusion/include/size.hpp> | |
17 | #include <boost/fusion/include/value_of.hpp> | |
18 | #include <boost/type_traits/integral_constant.hpp> | |
19 | #include <boost/type_traits/remove_const.hpp> | |
20 | #include <boost/type_traits/remove_reference.hpp> | |
21 | ||
22 | #include "fixture.hpp" | |
23 | ||
24 | namespace test_detail | |
25 | { | |
26 | struct adapted_sequence | |
27 | { | |
28 | adapted_sequence() : value_() {} | |
29 | explicit adapted_sequence(int value) : value_(value) {} | |
30 | int value_; | |
31 | }; | |
32 | ||
33 | bool operator==(adapted_sequence const& lhs, adapted_sequence const& rhs) | |
34 | { | |
35 | return lhs.value_ == rhs.value_; | |
36 | } | |
37 | ||
38 | bool operator!=(adapted_sequence const& lhs, adapted_sequence const& rhs) | |
39 | { | |
40 | return lhs.value_ != rhs.value_; | |
41 | } | |
42 | ||
43 | template <template <typename> class Scenario> | |
44 | struct can_convert_using | |
45 | { | |
46 | template <typename T> | |
47 | struct to | |
48 | { | |
49 | static bool can_convert_(boost::true_type /* skip */) | |
50 | { | |
51 | return true; | |
52 | } | |
53 | ||
54 | static bool can_convert_(boost::false_type /* skip */) | |
55 | { | |
56 | using namespace boost::fusion; | |
57 | return | |
58 | run<Scenario<T> >(typename result_of::as_deque<T>::type()) && | |
59 | run<Scenario<T> >(typename result_of::as_list<T>::type()) && | |
60 | run<Scenario<T> >(typename result_of::as_vector<T>::type()); | |
61 | } | |
62 | ||
63 | template <typename Source, typename Expected> | |
64 | bool operator()(Source const&, Expected const&) const | |
65 | { | |
66 | // bug when converting single element sequences in C++03 and | |
67 | // C++11... | |
68 | // not_<not_<is_convertible<sequence<sequence<int>>, int > | |
69 | // is invalid check | |
70 | typedef typename ::boost::fusion::result_of::size<T>::type seq_size; | |
71 | return can_convert_( | |
72 | boost::integral_constant<bool, seq_size::value == 1>() | |
73 | ); | |
74 | } | |
75 | }; | |
76 | }; | |
77 | ||
78 | template <typename T> | |
79 | struct can_construct_from_elements | |
80 | { | |
81 | template <typename Source, typename Expected> | |
82 | bool operator()(Source const&, Expected const&) const | |
83 | { | |
84 | // constructing a nested sequence of one is the complicated case to | |
85 | // disambiguate from a conversion-copy, so focus on that | |
86 | typedef typename boost::fusion::result_of::size<T>::type seq_size; | |
87 | return can_construct_( | |
88 | boost::integral_constant<int, seq_size::value>() | |
89 | ); | |
90 | } | |
91 | ||
92 | template <int Size> | |
93 | static bool can_construct_(boost::integral_constant<int, Size>) | |
94 | { | |
95 | return Size == 0 || Size == 2 || Size == 3; | |
96 | } | |
97 | ||
98 | static bool can_construct_(boost::integral_constant<int, 1>) | |
99 | { | |
100 | typedef typename ::boost::remove_reference< | |
101 | typename ::boost::remove_const< | |
102 | typename ::boost::fusion::result_of::value_of< | |
103 | typename ::boost::fusion::result_of::begin<T>::type | |
104 | >::type | |
105 | >::type | |
106 | >::type element; | |
107 | ||
108 | return run< can_construct<T> >(element(), T()); | |
109 | } | |
110 | }; | |
111 | ||
112 | template <typename T> | |
113 | struct can_nest | |
114 | { | |
115 | template <typename Source, typename Expected> | |
116 | bool operator()(Source const& source, Expected const& expected) | |
117 | { | |
118 | return | |
b32b8144 | 119 | run< can_copy<T> >(source, expected) && |
7c673cae FG |
120 | run< can_convert_using<can_copy>::to<T> >(source, expected) && |
121 | run< can_construct_from_elements<T> >(source, expected); | |
122 | } | |
123 | }; | |
124 | } // test_detail | |
125 | ||
126 | ||
127 | BOOST_FUSION_ADAPT_STRUCT(test_detail::adapted_sequence, (int, data)) | |
128 | ||
129 | template <template <typename> class Scenario> | |
130 | void | |
131 | test() | |
132 | { | |
133 | using namespace test_detail; | |
134 | ||
135 | BOOST_TEST(boost::fusion::traits::is_sequence<adapted_sequence>::value); | |
136 | BOOST_TEST(boost::fusion::size(adapted_sequence()) == 1); | |
137 | ||
138 | BOOST_TEST(( | |
139 | run< Scenario< FUSION_SEQUENCE< FUSION_SEQUENCE<> > > >( | |
140 | FUSION_SEQUENCE< FUSION_SEQUENCE<> >() | |
141 | ) | |
142 | )); | |
143 | BOOST_TEST(( | |
144 | run< Scenario<FUSION_SEQUENCE<FUSION_SEQUENCE<>, int> > >( | |
145 | FUSION_SEQUENCE< FUSION_SEQUENCE<>, int>(FUSION_SEQUENCE<>(), 325) | |
146 | ) | |
147 | )); | |
148 | BOOST_TEST(( | |
149 | run< Scenario< FUSION_SEQUENCE<int, FUSION_SEQUENCE<> > > >( | |
150 | FUSION_SEQUENCE< int, FUSION_SEQUENCE<> >(325, FUSION_SEQUENCE<>()) | |
151 | ) | |
152 | )); | |
153 | BOOST_TEST(( | |
154 | run< Scenario<FUSION_SEQUENCE<int, FUSION_SEQUENCE<>, float> > >( | |
155 | FUSION_SEQUENCE<int, FUSION_SEQUENCE<> , float>( | |
156 | 325, FUSION_SEQUENCE<>(), 2.0f | |
157 | ) | |
158 | ) | |
159 | )); | |
160 | ||
161 | BOOST_TEST(( | |
162 | run< Scenario< FUSION_SEQUENCE< FUSION_SEQUENCE<int> > > >( | |
163 | FUSION_SEQUENCE< FUSION_SEQUENCE<int> >(FUSION_SEQUENCE<int>(400)) | |
164 | ) | |
165 | )); | |
166 | BOOST_TEST(( | |
167 | run< Scenario< FUSION_SEQUENCE<adapted_sequence> > >( | |
168 | FUSION_SEQUENCE<adapted_sequence>(adapted_sequence(400)) | |
169 | ) | |
170 | )); | |
171 | BOOST_TEST(( | |
172 | run< Scenario<FUSION_SEQUENCE<FUSION_SEQUENCE<int>, int> > >( | |
173 | FUSION_SEQUENCE<FUSION_SEQUENCE<int>, int>( | |
174 | FUSION_SEQUENCE<int>(325), 400 | |
175 | ) | |
176 | ) | |
177 | )); | |
178 | BOOST_TEST(( | |
179 | run< Scenario<FUSION_SEQUENCE<adapted_sequence, int> > >( | |
180 | FUSION_SEQUENCE<adapted_sequence, int>(adapted_sequence(325), 400) | |
181 | ) | |
182 | )); | |
183 | BOOST_TEST(( | |
184 | run< Scenario< FUSION_SEQUENCE< int, FUSION_SEQUENCE<int> > > >( | |
185 | FUSION_SEQUENCE< int, FUSION_SEQUENCE<int> >( | |
186 | 325, FUSION_SEQUENCE<int>(400) | |
187 | ) | |
188 | ) | |
189 | )); | |
190 | BOOST_TEST(( | |
191 | run< Scenario< FUSION_SEQUENCE<int, adapted_sequence> > >( | |
192 | FUSION_SEQUENCE<int, adapted_sequence>(325, adapted_sequence(450)) | |
193 | ) | |
194 | )); | |
195 | BOOST_TEST(( | |
196 | run< Scenario< FUSION_SEQUENCE<int, FUSION_SEQUENCE<int>, int> > >( | |
197 | FUSION_SEQUENCE<int, FUSION_SEQUENCE<int>, int>( | |
198 | 500, FUSION_SEQUENCE<int>(350), 200 | |
199 | ) | |
200 | ) | |
201 | )); | |
202 | BOOST_TEST(( | |
203 | run< Scenario< FUSION_SEQUENCE<int, adapted_sequence, int> > >( | |
204 | FUSION_SEQUENCE<int, adapted_sequence, int>( | |
205 | 300, adapted_sequence(500), 400) | |
206 | ) | |
207 | )); | |
208 | ||
209 | BOOST_TEST(( | |
210 | run< Scenario< FUSION_SEQUENCE< FUSION_SEQUENCE<int, int> > > >( | |
211 | FUSION_SEQUENCE< FUSION_SEQUENCE<int, int> >( | |
212 | FUSION_SEQUENCE<int, int>(450, 500) | |
213 | ) | |
214 | ) | |
215 | )); | |
216 | BOOST_TEST(( | |
217 | run< Scenario< FUSION_SEQUENCE<FUSION_SEQUENCE<int, int>, int> > >( | |
218 | FUSION_SEQUENCE<FUSION_SEQUENCE<int, int>, int>( | |
219 | FUSION_SEQUENCE<int, int>(450, 500), 150 | |
220 | ) | |
221 | ) | |
222 | )); | |
223 | BOOST_TEST(( | |
224 | run< Scenario< FUSION_SEQUENCE< int, FUSION_SEQUENCE<int, int> > > >( | |
225 | FUSION_SEQUENCE< int, FUSION_SEQUENCE<int, int> >( | |
226 | 450, FUSION_SEQUENCE<int, int>(500, 150) | |
227 | ) | |
228 | ) | |
229 | )); | |
230 | BOOST_TEST(( | |
231 | run<Scenario< FUSION_SEQUENCE<int, FUSION_SEQUENCE<int, int>, int> > >( | |
232 | FUSION_SEQUENCE<int, FUSION_SEQUENCE<int, int>, int>( | |
233 | 150, FUSION_SEQUENCE<int, int>(250, 350), 450 | |
234 | ) | |
235 | ) | |
236 | )); | |
237 | ||
238 | BOOST_TEST(( | |
239 | run<Scenario<FUSION_SEQUENCE<FUSION_SEQUENCE<>, FUSION_SEQUENCE<> > > >( | |
240 | FUSION_SEQUENCE< FUSION_SEQUENCE<>, FUSION_SEQUENCE<> >( | |
241 | FUSION_SEQUENCE<>(), FUSION_SEQUENCE<>() | |
242 | ) | |
243 | ) | |
244 | )); | |
245 | BOOST_TEST(( | |
246 | run<Scenario<FUSION_SEQUENCE<FUSION_SEQUENCE<int>, FUSION_SEQUENCE<> > > >( | |
247 | FUSION_SEQUENCE< FUSION_SEQUENCE<int>, FUSION_SEQUENCE<> >( | |
248 | FUSION_SEQUENCE<int>(150), FUSION_SEQUENCE<>() | |
249 | ) | |
250 | ) | |
251 | )); | |
252 | BOOST_TEST(( | |
253 | run<Scenario<FUSION_SEQUENCE<FUSION_SEQUENCE<>, FUSION_SEQUENCE<int> > > >( | |
254 | FUSION_SEQUENCE< FUSION_SEQUENCE<>, FUSION_SEQUENCE<int> >( | |
255 | FUSION_SEQUENCE<>(), FUSION_SEQUENCE<int>(500) | |
256 | ) | |
257 | ) | |
258 | )); | |
259 | BOOST_TEST(( | |
260 | run<Scenario<FUSION_SEQUENCE<FUSION_SEQUENCE<int>, FUSION_SEQUENCE<int> > > >( | |
261 | FUSION_SEQUENCE< FUSION_SEQUENCE<int>, FUSION_SEQUENCE<int> >( | |
262 | FUSION_SEQUENCE<int>(155), FUSION_SEQUENCE<int>(255) | |
263 | ) | |
264 | ) | |
265 | )); | |
266 | BOOST_TEST(( | |
267 | run< Scenario< | |
268 | FUSION_SEQUENCE< FUSION_SEQUENCE<int, int>, FUSION_SEQUENCE<int> > | |
269 | > >( | |
270 | FUSION_SEQUENCE< FUSION_SEQUENCE<int, int>, FUSION_SEQUENCE<int> >( | |
271 | FUSION_SEQUENCE<int, int>(222, 333), FUSION_SEQUENCE<int>(444) | |
272 | ) | |
273 | ) | |
274 | )); | |
275 | BOOST_TEST(( | |
276 | run< Scenario< | |
277 | FUSION_SEQUENCE< FUSION_SEQUENCE<int>, FUSION_SEQUENCE<int, int> > | |
278 | > >( | |
279 | FUSION_SEQUENCE< FUSION_SEQUENCE<int>, FUSION_SEQUENCE<int, int> >( | |
280 | FUSION_SEQUENCE<int>(100), FUSION_SEQUENCE<int, int>(300, 400) | |
281 | ) | |
282 | ) | |
283 | )); | |
284 | BOOST_TEST(( | |
285 | run< Scenario< | |
286 | FUSION_SEQUENCE< FUSION_SEQUENCE<int, int>, FUSION_SEQUENCE<int, int> > | |
287 | > >( | |
288 | FUSION_SEQUENCE< FUSION_SEQUENCE<int, int>, FUSION_SEQUENCE<int, int> >( | |
289 | FUSION_SEQUENCE<int, int>(600, 700) | |
290 | , FUSION_SEQUENCE<int, int>(800, 900) | |
291 | ) | |
292 | ) | |
293 | )); | |
294 | ||
295 | ||
296 | // Ignore desired scenario, and cheat to make these work | |
297 | BOOST_TEST(( | |
298 | run< can_lvalue_construct< FUSION_SEQUENCE<FUSION_SEQUENCE<>&> > >( | |
299 | FUSION_SEQUENCE<>() | |
300 | , FUSION_SEQUENCE< FUSION_SEQUENCE<> >() | |
301 | ) | |
302 | )); | |
303 | BOOST_TEST(( | |
304 | run< can_construct< FUSION_SEQUENCE<const FUSION_SEQUENCE<>&> > >( | |
305 | FUSION_SEQUENCE<>() | |
306 | , FUSION_SEQUENCE< FUSION_SEQUENCE<> >() | |
307 | ) | |
308 | )); | |
309 | BOOST_TEST(( | |
310 | run< can_lvalue_construct< FUSION_SEQUENCE<FUSION_SEQUENCE<int>&> > >( | |
311 | FUSION_SEQUENCE<int>(300) | |
312 | , FUSION_SEQUENCE< FUSION_SEQUENCE<int> >(FUSION_SEQUENCE<int>(300)) | |
313 | ) | |
314 | )); | |
315 | BOOST_TEST(( | |
316 | run< can_construct< FUSION_SEQUENCE<const FUSION_SEQUENCE<int>&> > >( | |
317 | FUSION_SEQUENCE<int>(400) | |
318 | , FUSION_SEQUENCE< FUSION_SEQUENCE<int> >(FUSION_SEQUENCE<int>(400)) | |
319 | ) | |
320 | )); | |
321 | } |