1 /*=============================================================================
2 Copyright (C) 2016 Lee Clagett
3 Copyright (C) 2018 Kohei Takahashi
4
5 Distributed under the Boost Software License, Version 1.0. (See accompanying
6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 ==============================================================================*/
8
9 #include <boost/config.hpp>
10 #include <boost/detail/lightweight_test.hpp>
11 #include <boost/fusion/container/list.hpp>
12 #include <boost/fusion/container/vector.hpp>
13 #include <boost/type_traits/add_const.hpp>
14 #include <boost/type_traits/add_reference.hpp>
15 #include <boost/type_traits/integral_constant.hpp>
16 #include <boost/type_traits/is_constructible.hpp>
17 #include <boost/type_traits/is_convertible.hpp>
18 #include <boost/type_traits/remove_const.hpp>
19 #include <boost/type_traits/remove_reference.hpp>
20
21 struct convertible
22 {
convertibleconvertible23 convertible(int) {}
24 };
25
26 template <typename From, typename To>
is_convertible(bool has_conversion)27 bool is_convertible(bool has_conversion)
28 {
29 typedef typename boost::remove_reference<
30 typename boost::remove_const<From>::type
31 >::type from_rvalue;
32 typedef typename boost::add_reference<from_rvalue>::type from_lvalue;
33 typedef typename boost::add_const<from_lvalue>::type from_const_lvalue;
34
35 return
36 boost::is_convertible<from_rvalue, To>::value == has_conversion &&
37 boost::is_convertible<from_lvalue, To>::value == has_conversion &&
38 boost::is_convertible<from_const_lvalue, To>::value == has_conversion;
39 }
40
41 // is_constructible has a few requirements
42 #ifdef BOOST_TT_IS_CONSTRUCTIBLE_CONFORMING
43
44 #define FUSION_TEST_HAS_CONSTRUCTIBLE
45
46 template <typename To, typename... Args>
is_lvalue_constructible(bool has_constructor)47 bool is_lvalue_constructible(bool has_constructor)
48 {
49 return has_constructor ==
50 boost::is_constructible<
51 To
52 , typename boost::add_reference<Args>::type...
53 >::value;
54 }
55
56 template <typename To, typename... Args>
is_constructible_impl(bool has_constructor)57 bool is_constructible_impl(bool has_constructor)
58 {
59 return
60 boost::is_constructible<To, Args...>::value == has_constructor &&
61 is_lvalue_constructible<To, Args...>(has_constructor) &&
62 is_lvalue_constructible<
63 To, typename boost::add_const<Args>::type...
64 >(has_constructor);
65 }
66
67 template <typename To, typename... Args>
is_constructible(bool has_constructor)68 bool is_constructible(bool has_constructor)
69 {
70 return
71 is_constructible_impl<
72 To
73 , typename boost::remove_reference<
74 typename boost::remove_const<Args>::type
75 >::type...
76 >(has_constructor);
77 }
78
test_constructible()79 void test_constructible()
80 {
81 BOOST_TEST((is_constructible< FUSION_SEQUENCE<> >(true)));
82
83 BOOST_TEST((is_constructible< FUSION_SEQUENCE<int> >(true)));
84 BOOST_TEST((is_constructible<FUSION_SEQUENCE<int>, int>(true)));
85
86 BOOST_TEST((is_constructible<FUSION_SEQUENCE<convertible>, int>(true)));
87 BOOST_TEST((
88 is_constructible<FUSION_SEQUENCE<convertible>, convertible>(true)
89 ));
90
91 // boost::is_constructible always fail to test ctor which takes 2 or more arguments on GCC 4.7.
92 #if !BOOST_WORKAROUND(BOOST_GCC, < 40700)
93 BOOST_TEST((
94 is_constructible<FUSION_SEQUENCE<int, int>, int, int>(true)
95 ));
96
97 BOOST_TEST((
98 is_constructible<FUSION_SEQUENCE<convertible, int>, int, int>(true)
99 ));
100 BOOST_TEST((
101 is_constructible<
102 FUSION_SEQUENCE<convertible, int>, convertible, int
103 >(true)
104 ));
105
106 BOOST_TEST((
107 is_constructible<FUSION_SEQUENCE<int, convertible>, int, int>(true)
108 ));
109 BOOST_TEST((
110 is_constructible<
111 FUSION_SEQUENCE<int, convertible>, int, convertible
112 >(true)
113 ));
114
115 BOOST_TEST((
116 is_constructible<
117 FUSION_SEQUENCE<convertible, convertible>, int, int
118 >(true)
119 ));
120 BOOST_TEST((
121 is_constructible<
122 FUSION_SEQUENCE<convertible, convertible>, convertible, int
123 >(true)
124 ));
125 BOOST_TEST((
126 is_constructible<
127 FUSION_SEQUENCE<convertible, convertible>, int, convertible
128 >(true)
129 ));
130 BOOST_TEST((
131 is_constructible<
132 FUSION_SEQUENCE<convertible, convertible>, convertible, convertible
133 >(true)
134 ));
135 #endif // !(gcc < 4.7)
136 }
137
138 #endif // is_constructible is available
139
test_convertible(bool has_seq_conversion)140 void test_convertible(bool has_seq_conversion)
141 {
142 BOOST_TEST((is_convertible<int, FUSION_SEQUENCE<> >(false)));
143 BOOST_TEST((is_convertible<int, FUSION_SEQUENCE<int> >(false)));
144 BOOST_TEST((is_convertible<int, FUSION_SEQUENCE<const int&> >(false)));
145 BOOST_TEST((is_convertible<int, FUSION_SEQUENCE<convertible> >(false)));
146 BOOST_TEST((
147 is_convertible<int, FUSION_SEQUENCE<const convertible&> >(false)
148 ));
149 BOOST_TEST((is_convertible<int, FUSION_SEQUENCE<int, int> >(false)));
150 BOOST_TEST((
151 is_convertible<int, FUSION_SEQUENCE<const int&, const int&> >(false)
152 ));
153 BOOST_TEST((is_convertible<int, FUSION_SEQUENCE<convertible, int> >(false)));
154 BOOST_TEST((
155 is_convertible<int, FUSION_SEQUENCE<const convertible&, const int&> >(false)
156 ));
157 BOOST_TEST((is_convertible<int, FUSION_SEQUENCE<int, convertible> >(false)));
158 BOOST_TEST((
159 is_convertible<int, FUSION_SEQUENCE<const int&, const convertible&> >(false)
160 ));
161 BOOST_TEST((
162 is_convertible<int, FUSION_SEQUENCE<convertible, convertible> >(false)
163 ));
164 BOOST_TEST((
165 is_convertible<
166 int, FUSION_SEQUENCE<const convertible&, const convertible&>
167 >(false)
168 ));
169
170 BOOST_TEST((is_convertible<FUSION_SEQUENCE<>, FUSION_SEQUENCE<> >(true)));
171 BOOST_TEST((
172 is_convertible<FUSION_SEQUENCE<int>, FUSION_SEQUENCE<int> >(true)
173 ));
174 BOOST_TEST((
175 is_convertible<FUSION_SEQUENCE<int>, FUSION_SEQUENCE<const int&> >(true)
176 ));
177 BOOST_TEST((
178 is_convertible<FUSION_SEQUENCE<int>, FUSION_SEQUENCE<convertible> >(true)
179 ));
180 BOOST_TEST((
181 is_convertible<FUSION_SEQUENCE<int, int>, FUSION_SEQUENCE<int, int> >(true)
182 ));
183 BOOST_TEST((
184 is_convertible<
185 FUSION_SEQUENCE<int, int>, FUSION_SEQUENCE<const int&, const int&>
186 >(true)
187 ));
188 BOOST_TEST((
189 is_convertible<
190 FUSION_SEQUENCE<int, int>, FUSION_SEQUENCE<convertible, int>
191 >(true)
192 ));
193 BOOST_TEST((
194 is_convertible<
195 FUSION_SEQUENCE<int, int>, FUSION_SEQUENCE<int, convertible>
196 >(true)
197 ));
198 BOOST_TEST((
199 is_convertible<
200 FUSION_SEQUENCE<int, int>
201 , FUSION_SEQUENCE<convertible, convertible>
202 >(true)
203 ));
204
205 BOOST_TEST((
206 is_convertible<
207 FUSION_ALT_SEQUENCE<>, FUSION_SEQUENCE<>
208 >(has_seq_conversion)
209 ));
210 BOOST_TEST((
211 is_convertible<
212 FUSION_ALT_SEQUENCE<int>, FUSION_SEQUENCE<int>
213 >(has_seq_conversion)
214 ));
215 BOOST_TEST((
216 is_convertible<
217 FUSION_ALT_SEQUENCE<int>, FUSION_SEQUENCE<const int&>
218 >(has_seq_conversion)
219 ));
220 BOOST_TEST((
221 is_convertible<
222 FUSION_ALT_SEQUENCE<int>, FUSION_SEQUENCE<convertible>
223 >(has_seq_conversion)
224 ));
225 BOOST_TEST((
226 is_convertible<
227 FUSION_ALT_SEQUENCE<int, int>, FUSION_SEQUENCE<int, int>
228 >(has_seq_conversion)
229 ));
230 BOOST_TEST((
231 is_convertible<
232 FUSION_ALT_SEQUENCE<int, int>
233 , FUSION_SEQUENCE<const int&, const int&>
234 >(has_seq_conversion)
235 ));
236 BOOST_TEST((
237 is_convertible<
238 FUSION_ALT_SEQUENCE<int, int>, FUSION_SEQUENCE<convertible, int>
239 >(has_seq_conversion)
240 ));
241 BOOST_TEST((
242 is_convertible<
243 FUSION_ALT_SEQUENCE<int, int>, FUSION_SEQUENCE<int, convertible>
244 >(has_seq_conversion)
245 ));
246 BOOST_TEST((
247 is_convertible<
248 FUSION_ALT_SEQUENCE<int, int>
249 , FUSION_SEQUENCE<convertible, convertible>
250 >(has_seq_conversion)
251 ));
252 }
253
254