1 | // Copyright Daniel Wallin 2006. |
2 | // Distributed under the Boost Software License, Version 1.0. |
3 | // (See accompanying file LICENSE_1_0.txt or copy at |
4 | // http://www.boost.org/LICENSE_1_0.txt) |
5 | |
6 | #include <boost/parameter/config.hpp> |
7 | #include <boost/parameter/preprocessor.hpp> |
8 | #include <boost/parameter/name.hpp> |
9 | #include <boost/tuple/tuple.hpp> |
10 | #include <map> |
11 | #include <string> |
12 | #include "basics.hpp" |
13 | |
14 | #if defined(BOOST_PARAMETER_CAN_USE_MP11) |
15 | #include <boost/parameter/value_type.hpp> |
16 | #include <boost/mp11/map.hpp> |
17 | #include <boost/core/enable_if.hpp> |
18 | #include <type_traits> |
19 | #else |
20 | #include <boost/mpl/bool.hpp> |
21 | #include <boost/mpl/if.hpp> |
22 | #include <boost/type_traits/is_convertible.hpp> |
23 | #if !defined(BOOST_NO_SFINAE) |
24 | #include <boost/parameter/value_type.hpp> |
25 | #include <boost/mpl/has_key.hpp> |
26 | #include <boost/core/enable_if.hpp> |
27 | #include <boost/type_traits/is_same.hpp> |
28 | #endif |
29 | #endif |
30 | |
31 | namespace test { |
32 | |
33 | BOOST_PARAMETER_NAME(expected) |
34 | BOOST_PARAMETER_NAME(x) |
35 | BOOST_PARAMETER_NAME(y) |
36 | BOOST_PARAMETER_NAME(z) |
37 | |
38 | #if defined(BOOST_PARAMETER_CAN_USE_MP11) |
39 | template <typename To> |
40 | struct predicate |
41 | { |
42 | template <typename From, typename Args> |
43 | using fn = std::is_convertible<From,To>; |
44 | }; |
45 | |
46 | BOOST_PARAMETER_FUNCTION((int), f, test::tag, |
47 | (required |
48 | (expected, *) |
49 | ) |
50 | (deduced |
51 | (required |
52 | (x, *(test::predicate<int>)) |
53 | (y, *(test::predicate<std::string>)) |
54 | ) |
55 | ) |
56 | ) |
57 | #else // !defined(BOOST_PARAMETER_CAN_USE_MP11) |
58 | struct predicate_int |
59 | { |
60 | template <typename From, typename Args> |
61 | struct apply |
62 | : boost::mpl::if_< |
63 | boost::is_convertible<From,int> |
64 | , boost::mpl::true_ |
65 | , boost::mpl::false_ |
66 | > |
67 | { |
68 | }; |
69 | }; |
70 | |
71 | struct predicate_string |
72 | { |
73 | template <typename From, typename Args> |
74 | struct apply |
75 | : boost::mpl::if_< |
76 | boost::is_convertible<From,std::string> |
77 | , boost::mpl::true_ |
78 | , boost::mpl::false_ |
79 | > |
80 | { |
81 | }; |
82 | }; |
83 | |
84 | BOOST_PARAMETER_FUNCTION((int), f, test::tag, |
85 | (required |
86 | (expected, *) |
87 | ) |
88 | (deduced |
89 | (required |
90 | (x, *(test::predicate_int)) |
91 | (y, *(test::predicate_string)) |
92 | ) |
93 | ) |
94 | ) |
95 | #endif // BOOST_PARAMETER_CAN_USE_MP11 |
96 | { |
97 | BOOST_TEST(test::equal(x, boost::tuples::get<0>(expected))); |
98 | BOOST_TEST(test::equal(y, boost::tuples::get<1>(expected))); |
99 | return 1; |
100 | } |
101 | |
102 | struct X |
103 | { |
104 | X(int x_ = -1) : x(x_) |
105 | { |
106 | } |
107 | |
108 | bool operator==(X const& other) const |
109 | { |
110 | return this->x == other.x; |
111 | } |
112 | |
113 | int x; |
114 | }; |
115 | |
116 | #if defined(BOOST_PARAMETER_CAN_USE_MP11) |
117 | BOOST_PARAMETER_FUNCTION((int), g, test::tag, |
118 | (required |
119 | (expected, *) |
120 | ) |
121 | (deduced |
122 | (required |
123 | (x, *(test::predicate<int>)) |
124 | (y, *(test::predicate<std::string>)) |
125 | ) |
126 | (optional |
127 | (z, *(test::predicate<test::X>), test::X()) |
128 | ) |
129 | ) |
130 | ) |
131 | #else // !defined(BOOST_PARAMETER_CAN_USE_MP11) |
132 | struct predicate_X |
133 | { |
134 | template <typename From, typename Args> |
135 | struct apply |
136 | : boost::mpl::if_< |
137 | boost::is_convertible<From,test::X> |
138 | , boost::mpl::true_ |
139 | , boost::mpl::false_ |
140 | > |
141 | { |
142 | }; |
143 | }; |
144 | |
145 | BOOST_PARAMETER_FUNCTION((int), g, tag, |
146 | (required |
147 | (expected, *) |
148 | ) |
149 | (deduced |
150 | (required |
151 | (x, *(test::predicate_int)) |
152 | (y, *(test::predicate_string)) |
153 | ) |
154 | (optional |
155 | (z, *(test::predicate_X), test::X()) |
156 | ) |
157 | ) |
158 | ) |
159 | #endif // BOOST_PARAMETER_CAN_USE_MP11 |
160 | { |
161 | BOOST_TEST(test::equal(x, boost::tuples::get<0>(expected))); |
162 | BOOST_TEST(test::equal(y, boost::tuples::get<1>(expected))); |
163 | BOOST_TEST(test::equal(z, boost::tuples::get<2>(expected))); |
164 | return 1; |
165 | } |
166 | |
167 | #if defined(BOOST_PARAMETER_CAN_USE_MP11) |
168 | BOOST_PARAMETER_FUNCTION((int), sfinae, test::tag, |
169 | (deduced |
170 | (required |
171 | (x, *(test::predicate<std::string>)) |
172 | ) |
173 | ) |
174 | ) |
175 | #else |
176 | BOOST_PARAMETER_FUNCTION((int), sfinae, test::tag, |
177 | (deduced |
178 | (required |
179 | (x, *(test::predicate_string)) |
180 | ) |
181 | ) |
182 | ) |
183 | #endif |
184 | { |
185 | return 1; |
186 | } |
187 | |
188 | #if !defined(BOOST_NO_SFINAE) |
189 | // On compilers that actually support SFINAE, add another overload |
190 | // that is an equally good match and can only be in the overload set |
191 | // when the others are not. This tests that the SFINAE is actually |
192 | // working. On all other compilers we're just checking that everything |
193 | // about SFINAE-enabled code will work, except of course the SFINAE. |
194 | template <typename A0> |
195 | typename boost::enable_if< |
196 | #if defined(BOOST_PARAMETER_CAN_USE_MP11) |
197 | std::is_same<int,A0> |
198 | #else |
199 | typename boost::mpl::if_< |
200 | boost::is_same<int,A0> |
201 | , boost::mpl::true_ |
202 | , boost::mpl::false_ |
203 | >::type |
204 | #endif |
205 | , int |
206 | >::type |
207 | sfinae(A0 const& a0) |
208 | { |
209 | return 0; |
210 | } |
211 | |
212 | #if defined(LIBS_PARAMETER_TEST_COMPILE_FAILURE_VENDOR_SPECIFIC) || \ |
213 | !BOOST_WORKAROUND(BOOST_MSVC, < 1800) |
214 | // Test support for two different Boost.Parameter-enabled |
215 | // function call operator overloads. |
216 | class char_read_base |
217 | { |
218 | int index; |
219 | char const* key; |
220 | |
221 | public: |
222 | template <typename Args> |
223 | explicit char_read_base(Args const& args) |
224 | : index(args[test::_y]), key(args[test::_z]) |
225 | { |
226 | } |
227 | |
228 | BOOST_PARAMETER_FUNCTION_CALL_OPERATOR((void), test::tag, |
229 | (deduced |
230 | (required |
231 | (y, (int)) |
232 | (z, (char const*)) |
233 | ) |
234 | ) |
235 | ) |
236 | { |
237 | this->index = y; |
238 | this->key = z; |
239 | } |
240 | |
241 | BOOST_PARAMETER_CONST_FUNCTION_CALL_OPERATOR((char), test::tag, |
242 | (deduced |
243 | (required |
244 | (y, (bool)) |
245 | (z, (std::map<char const*,std::string>)) |
246 | ) |
247 | ) |
248 | ) |
249 | { |
250 | return y ? ( |
251 | (z.find(this->key)->second)[this->index] |
252 | ) : this->key[this->index]; |
253 | } |
254 | }; |
255 | |
256 | struct char_reader : public char_read_base |
257 | { |
258 | BOOST_PARAMETER_CONSTRUCTOR(char_reader, (char_read_base), test::tag, |
259 | (deduced |
260 | (required |
261 | (y, (int)) |
262 | (z, (char const*)) |
263 | ) |
264 | ) |
265 | ) |
266 | }; |
267 | #endif // MSVC-11.0- |
268 | |
269 | // Test Boost.Parameter-enabled functions |
270 | // with parameter-dependent return types. |
271 | #if !defined(LIBS_PARAMETER_TEST_COMPILE_FAILURE) |
272 | #if defined(BOOST_PARAMETER_CAN_USE_MP11) |
273 | BOOST_PARAMETER_FUNCTION( |
274 | ( |
275 | boost::lazy_enable_if< |
276 | boost::mp11::mp_map_contains<Args,test::tag::y> |
277 | , boost::parameter::value_type<Args,test::tag::y> |
278 | > |
279 | ), return_y, test::tag, |
280 | (deduced |
281 | (required |
282 | (x, (std::map<char const*,std::string>)) |
283 | (y, (char const*)) |
284 | ) |
285 | (optional |
286 | (z, (int), 4) |
287 | ) |
288 | ) |
289 | ) |
290 | #else // !defined(BOOST_PARAMETER_CAN_USE_MP11) |
291 | BOOST_PARAMETER_FUNCTION( |
292 | ( |
293 | boost::lazy_enable_if< |
294 | typename boost::mpl::has_key<Args,test::tag::y>::type |
295 | , boost::parameter::value_type<Args,test::tag::y> |
296 | > |
297 | ), return_y, test::tag, |
298 | (deduced |
299 | (required |
300 | (x, (std::map<char const*,std::string>)) |
301 | (y, (char const*)) |
302 | ) |
303 | (optional |
304 | (z, (int), 4) |
305 | ) |
306 | ) |
307 | ) |
308 | #endif // BOOST_PARAMETER_CAN_USE_MP11 |
309 | { |
310 | return y; |
311 | } |
312 | #endif // LIBS_PARAMETER_TEST_COMPILE_FAILURE |
313 | #endif // BOOST_NO_SFINAE |
314 | |
315 | #if defined(LIBS_PARAMETER_TEST_COMPILE_FAILURE) |
316 | BOOST_PARAMETER_FUNCTION( |
317 | (typename boost::parameter::value_type<Args,test::tag::y>::type), |
318 | return_y, test::tag, |
319 | (deduced |
320 | (required |
321 | (x, (std::map<char const*,std::string>)) |
322 | (y, (char const*)) |
323 | ) |
324 | (optional |
325 | (z, (int), 4) |
326 | ) |
327 | ) |
328 | ) |
329 | { |
330 | return y; |
331 | } |
332 | #endif // defined(LIBS_PARAMETER_TEST_COMPILE_FAILURE) |
333 | } // namespace test |
334 | |
335 | #include <boost/core/lightweight_test.hpp> |
336 | |
337 | int main() |
338 | { |
339 | test::f( |
340 | a0: boost::make_tuple(t0: 0, t1: std::string("foo" )) |
341 | , a1: test::_x = 0 |
342 | , a2: test::_y = std::string("foo" ) |
343 | ); |
344 | test::f( |
345 | a0: boost::make_tuple(t0: 0, t1: std::string("foo" )) |
346 | , a1: 0 |
347 | , a2: std::string("foo" ) |
348 | ); |
349 | test::f( |
350 | a0: boost::make_tuple(t0: 0, t1: std::string("foo" )) |
351 | , a1: std::string("foo" ) |
352 | , a2: 0 |
353 | ); |
354 | test::f( |
355 | a0: boost::make_tuple(t0: 0, t1: std::string("foo" )) |
356 | , a1: test::_y = std::string("foo" ) |
357 | , a2: 0 |
358 | ); |
359 | test::f( |
360 | a0: boost::make_tuple(t0: 0, t1: std::string("foo" )) |
361 | , a1: test::_x = 0 |
362 | , a2: std::string("foo" ) |
363 | ); |
364 | test::f( |
365 | a0: boost::make_tuple(t0: 0, t1: std::string("foo" )) |
366 | , a1: 0 |
367 | , a2: test::_y = std::string("foo" ) |
368 | ); |
369 | test::g( |
370 | a0: boost::make_tuple(t0: 0, t1: std::string("foo" ), t2: test::X()) |
371 | , a1: test::_x = 0 |
372 | , a2: test::_y = std::string("foo" ) |
373 | ); |
374 | test::g( |
375 | a0: boost::make_tuple(t0: 0, t1: std::string("foo" ), t2: test::X()) |
376 | , a1: 0 |
377 | , a2: std::string("foo" ) |
378 | ); |
379 | test::g( |
380 | a0: boost::make_tuple(t0: 0, t1: std::string("foo" ), t2: test::X()) |
381 | , a1: std::string("foo" ) |
382 | , a2: 0 |
383 | ); |
384 | test::g( |
385 | a0: boost::make_tuple(t0: 0, t1: std::string("foo" ), t2: test::X()) |
386 | , a1: test::_y = std::string("foo" ) |
387 | , a2: 0 |
388 | ); |
389 | test::g( |
390 | a0: boost::make_tuple(t0: 0, t1: std::string("foo" ), t2: test::X()) |
391 | , a1: test::_x = 0 |
392 | , a2: std::string("foo" ) |
393 | ); |
394 | test::g( |
395 | a0: boost::make_tuple(t0: 0, t1: std::string("foo" ), t2: test::X()) |
396 | , a1: 0 |
397 | , a2: test::_y = std::string("foo" ) |
398 | ); |
399 | test::g( |
400 | a0: boost::make_tuple(t0: 0, t1: std::string("foo" ), t2: test::X(1)) |
401 | , a1: 0 |
402 | , a2: test::_y = std::string("foo" ) |
403 | , a3: test::X(1) |
404 | ); |
405 | test::g( |
406 | a0: boost::make_tuple(t0: 0, t1: std::string("foo" ), t2: test::X(1)) |
407 | , a1: test::X(1) |
408 | , a2: 0 |
409 | , a3: test::_y = std::string("foo" ) |
410 | ); |
411 | |
412 | std::map<char const*,std::string> k2s; |
413 | #if !defined(BOOST_NO_SFINAE) |
414 | char const* keys[] = {"foo" , "bar" , "baz" }; |
415 | BOOST_TEST_EQ(1, test::sfinae(keys[0])); |
416 | BOOST_TEST_EQ(0, test::sfinae(0)); |
417 | #if defined(LIBS_PARAMETER_TEST_COMPILE_FAILURE_VENDOR_SPECIFIC) || \ |
418 | !BOOST_WORKAROUND(BOOST_MSVC, < 1800) |
419 | k2s[keys[0]] = std::string("qux" ); |
420 | k2s[keys[1]] = std::string("wmb" ); |
421 | k2s[keys[2]] = std::string("zxc" ); |
422 | test::char_reader r(keys[0], 0); |
423 | BOOST_TEST_EQ('q', (r(k2s, true))); |
424 | BOOST_TEST_EQ('f', (r(k2s, false))); |
425 | r(keys[1], 1); |
426 | BOOST_TEST_EQ('m', (r(k2s, true))); |
427 | BOOST_TEST_EQ('a', (r(k2s, false))); |
428 | r(keys[2], 2); |
429 | BOOST_TEST_EQ('c', (r(k2s, true))); |
430 | BOOST_TEST_EQ('z', (r(k2s, false))); |
431 | #endif // MSVC-11.0- |
432 | #if !defined(LIBS_PARAMETER_TEST_COMPILE_FAILURE) |
433 | BOOST_TEST_EQ(keys[1], test::return_y(2, k2s, keys[1])); |
434 | #endif |
435 | #endif // BOOST_NO_SFINAE |
436 | |
437 | #if defined(LIBS_PARAMETER_TEST_COMPILE_FAILURE) |
438 | BOOST_TEST_EQ(keys[1], test::return_y(2, k2s, keys[1])); |
439 | #endif |
440 | |
441 | return boost::report_errors(); |
442 | } |
443 | |
444 | |