• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     {
adapted_sequencetest_detail::adapted_sequence28         adapted_sequence() : value_() {}
adapted_sequencetest_detail::adapted_sequence29         explicit adapted_sequence(int value) : value_(value) {}
30         int value_;
31     };
32 
operator ==(adapted_sequence const & lhs,adapted_sequence const & rhs)33     bool operator==(adapted_sequence const& lhs, adapted_sequence const& rhs)
34     {
35         return lhs.value_ == rhs.value_;
36     }
37 
operator !=(adapted_sequence const & lhs,adapted_sequence const & rhs)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         {
can_convert_test_detail::can_convert_using::to49             static bool can_convert_(boost::true_type /* skip */)
50             {
51                 return true;
52             }
53 
can_convert_test_detail::can_convert_using::to54             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>
operator ()test_detail::can_convert_using::to64             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>
operator ()test_detail::can_construct_from_elements82         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>
can_construct_test_detail::can_construct_from_elements93         static bool can_construct_(boost::integral_constant<int, Size>)
94         {
95             return Size == 0 || Size == 2 || Size == 3;
96         }
97 
can_construct_test_detail::can_construct_from_elements98         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>
operator ()test_detail::can_nest116         bool operator()(Source const& source, Expected const& expected)
117         {
118             return
119                 run< can_copy<T> >(source, expected) &&
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
test()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 }
322