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
31namespace 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
337int 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

source code of boost/libs/parameter/test/preprocessor_deduced.cpp