• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/preprocessor.hpp>
7 #include <boost/parameter/binding.hpp>
8 #include <boost/parameter/config.hpp>
9 #include "basics.hpp"
10 
11 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
12 #include <type_traits>
13 #else
14 #include <boost/mpl/bool.hpp>
15 #include <boost/mpl/if.hpp>
16 #include <boost/type_traits/is_same.hpp>
17 #endif
18 
19 namespace test {
20 
21     BOOST_PARAMETER_BASIC_FUNCTION((int), f, test::tag,
22         (required
23             (tester, *)
24             (name, *)
25         )
26         (optional
27             (value, *)
28             (index, (int))
29         )
30     )
31     {
32         typedef typename boost::parameter::binding<
33             Args,test::tag::index,int&
34         >::type index_type;
35 
36 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
37         static_assert(
38             std::is_same<index_type,int&>::value
39           , "index_type == int&"
40         );
41 #else
42         BOOST_MPL_ASSERT((
43             typename boost::mpl::if_<
44                 boost::is_same<index_type,int&>
45               , boost::mpl::true_
46               , boost::mpl::false_
47             >::type
48         ));
49 #endif
50 
51         args[test::_tester](
52             args[test::_name]
53           , args[test::_value | 1.f]
54           , args[test::_index | 2]
55         );
56 
57         return 1;
58     }
59 } // namespace test
60 
61 #include <boost/parameter/value_type.hpp>
62 
63 #if !defined(BOOST_PARAMETER_CAN_USE_MP11)
64 #include <boost/type_traits/remove_const.hpp>
65 #endif
66 
67 namespace test {
68 
69     BOOST_PARAMETER_BASIC_FUNCTION((int), g, test::tag,
70         (required
71             (tester, *)
72             (name, *)
73         )
74         (optional
75             (value, *)
76             (index, (int))
77         )
78     )
79     {
80         typedef typename boost::parameter::value_type<
81             Args,test::tag::index,int
82         >::type index_type;
83 
84 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
85         static_assert(
86             std::is_same<
87                 typename std::remove_const<index_type>::type
88               , int
89             >::value
90           , "remove_const<index_type>::type == int"
91         );
92 #else
93         BOOST_MPL_ASSERT((
94             typename boost::mpl::if_<
95                 boost::is_same<
96                     typename boost::remove_const<index_type>::type
97                   , int
98                 >
99               , boost::mpl::true_
100               , boost::mpl::false_
101             >::type
102         ));
103 #endif
104 
105         args[test::_tester](
106             args[test::_name]
107           , args[test::_value | 1.f]
108           , args[test::_index | 2]
109         );
110 
111         return 1;
112     }
113 } // namespace test
114 
115 #if !defined(BOOST_PARAMETER_CAN_USE_MP11)
116 #include <boost/type_traits/remove_reference.hpp>
117 #endif
118 
119 namespace test {
120 
121     BOOST_PARAMETER_FUNCTION((int), h, test::tag,
122         (required
123             (tester, *)
124             (name, *)
125         )
126         (optional
127             (value, *, 1.f)
128             (index, (int), 2)
129         )
130     )
131     {
132 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
133         static_assert(
134             std::is_same<
135                 typename std::remove_const<
136                     typename std::remove_reference<index_type>::type
137                 >::type
138               , int
139             >::value
140           , "remove_cref<index_type>::type == int"
141         );
142 #elif !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && \
143     !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
144         BOOST_MPL_ASSERT((
145             typename boost::mpl::if_<
146                 boost::is_same<
147                     typename boost::remove_const<
148                         typename boost::remove_reference<index_type>::type
149                     >::type
150                   , int
151                 >
152               , boost::mpl::true_
153               , boost::mpl::false_
154             >::type
155         ));
156 #endif  // BOOST_PARAMETER_CAN_USE_MP11 || Borland/MSVC workarounds not needed
157 
158         tester(name, value, index);
159 
160         return 1;
161     }
162 
163     BOOST_PARAMETER_FUNCTION((int), h2, test::tag,
164         (required
165             (tester, *)
166             (name, *)
167         )
168         (optional
169             (value, *, 1.f)
170             (index, (int), static_cast<int>(value * 2))
171         )
172     )
173     {
174 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
175         static_assert(
176             std::is_same<
177                 typename std::remove_const<
178                     typename std::remove_reference<index_type>::type
179                 >::type
180               , int
181             >::value
182           , "remove_cref<index_type>::type == int"
183         );
184 #elif !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && \
185     !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
186         BOOST_MPL_ASSERT((
187             typename boost::mpl::if_<
188                 boost::is_same<
189                     typename boost::remove_const<
190                         typename boost::remove_reference<index_type>::type
191                     >::type
192                   , int
193                 >
194               , boost::mpl::true_
195               , boost::mpl::false_
196             >::type
197         ));
198 #endif  // BOOST_PARAMETER_CAN_USE_MP11 || Borland/MSVC workarounds not needed
199 
200         tester(name, value, index);
201 
202         return 1;
203     }
204 } // namespace test
205 
206 #include <string>
207 
208 #if !defined(BOOST_NO_SFINAE)
209 #include <boost/parameter/aux_/preprocessor/nullptr.hpp>
210 #include <boost/core/enable_if.hpp>
211 #if !defined(BOOST_PARAMETER_CAN_USE_MP11)
212 #include <boost/type_traits/is_base_of.hpp>
213 #include <boost/type_traits/is_convertible.hpp>
214 #endif
215 #endif
216 
217 namespace test {
218 
219     struct base_0
220     {
221         float f;
222         int i;
223 
224         template <typename Args>
base_0test::base_0225         explicit base_0(
226             Args const& args
227 #if !defined(BOOST_NO_SFINAE)
228           , typename boost::disable_if<
229                 typename boost::mpl::if_<
230                     boost::is_base_of<base_0,Args>
231                   , boost::mpl::true_
232                   , boost::mpl::false_
233                 >::type
234             >::type* = BOOST_PARAMETER_AUX_PP_NULLPTR
235 #endif  // BOOST_NO_SFINAE
236         ) : f(args[test::_value | 1.f]), i(args[test::_index | 2])
237         {
238         }
239     };
240 
241     struct class_0 : test::base_0
242     {
243         BOOST_PARAMETER_CONSTRUCTOR(class_0, (test::base_0), test::tag,
244             (optional
245                 (value, *)
246                 (index, *)
247             )
248         )
249 
250         BOOST_PARAMETER_BASIC_FUNCTION_CALL_OPERATOR((int), test::tag,
251             (optional
252                 (value, *)
253                 (index, *)
254             )
255         )
256         {
257             this->f = args[test::_value | 2.f];
258             this->i = args[test::_index | 1];
259             return 1;
260         }
261     };
262 
263     struct base_1
264     {
265         template <typename Args>
base_1test::base_1266         explicit base_1(
267             Args const& args
268 #if !defined(BOOST_NO_SFINAE)
269           , typename boost::disable_if<
270 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
271                 std::is_base_of<base_1,Args>
272 #else
273                 typename boost::mpl::if_<
274                     boost::is_base_of<base_1,Args>
275                   , boost::mpl::true_
276                   , boost::mpl::false_
277                 >::type
278 #endif
279             >::type* = BOOST_PARAMETER_AUX_PP_NULLPTR
280 #endif  // BOOST_NO_SFINAE
281         )
282         {
283             args[test::_tester](
284                 args[test::_name]
285               , args[test::_value | 1.f]
286               , args[test::_index | 2]
287             );
288         }
289     };
290 
291     struct class_1 : test::base_1
292     {
293         BOOST_PARAMETER_CONSTRUCTOR(class_1, (test::base_1), test::tag,
294             (required
295                 (tester, *)
296                 (name, *)
297             )
298             (optional
299                 (value, *)
300                 (index, *)
301             )
302         )
303 
304         BOOST_PARAMETER_BASIC_MEMBER_FUNCTION((int), f, test::tag,
305             (required
306                 (tester, *)
307                 (name, *)
308             )
309             (optional
310                 (value, *)
311                 (index, *)
312             )
313         )
314         {
315             args[test::_tester](
316                 args[test::_name]
317               , args[test::_value | 1.f]
318               , args[test::_index | 2]
319             );
320 
321             return 1;
322         }
323 
324         BOOST_PARAMETER_BASIC_CONST_MEMBER_FUNCTION((int), f, test::tag,
325             (required
326                 (tester, *)
327                 (name, *)
328             )
329             (optional
330                 (value, *)
331                 (index, *)
332             )
333         )
334         {
335             args[test::_tester](
336                 args[test::_name]
337               , args[test::_value | 1.f]
338               , args[test::_index | 2]
339             );
340 
341             return 1;
342         }
343 
344         BOOST_PARAMETER_MEMBER_FUNCTION((int), f2, test::tag,
345             (required
346                 (tester, *)
347                 (name, *)
348             )
349             (optional
350                 (value, *, 1.f)
351                 (index, *, 2)
352             )
353         )
354         {
355             tester(name, value, index);
356             return 1;
357         }
358 
359         BOOST_PARAMETER_CONST_MEMBER_FUNCTION((int), f2, test::tag,
360             (required
361                 (tester, *)
362                 (name, *)
363             )
364             (optional
365                 (value, *, 1.f)
366                 (index, *, 2)
367             )
368         )
369         {
370             tester(name, value, index);
371             return 1;
372         }
373 
374         BOOST_PARAMETER_MEMBER_FUNCTION((int), static f_static, test::tag,
375             (required
376                 (tester, *)
377                 (name, *)
378             )
379             (optional
380                 (value, *, 1.f)
381                 (index, *, 2)
382             )
383         )
384         {
385             tester(name, value, index);
386             return 1;
387         }
388 
389         BOOST_PARAMETER_FUNCTION_CALL_OPERATOR((int), test::tag,
390             (required
391                 (tester, *)
392                 (name, *)
393             )
394             (optional
395                 (value, *, 1.f)
396                 (index, *, 2)
397             )
398         )
399         {
400             tester(name, value, index);
401             return 1;
402         }
403 
404         BOOST_PARAMETER_CONST_FUNCTION_CALL_OPERATOR((int), test::tag,
405             (required
406                 (tester, *)
407                 (name, *)
408             )
409             (optional
410                 (value, *, 1.f)
411                 (index, *, 2)
412             )
413         )
414         {
415             tester(name, value, index);
416             return 1;
417         }
418     };
419 
420     BOOST_PARAMETER_FUNCTION((int), sfinae, test::tag,
421         (required
422             (name, (std::string))
423         )
424     )
425     {
426         return 1;
427     }
428 
429 #if !defined(BOOST_NO_SFINAE)
430     // On compilers that actually support SFINAE, add another overload
431     // that is an equally good match and can only be in the overload set
432     // when the others are not.  This tests that the SFINAE is actually
433     // working.  On all other compilers we're just checking that everything
434     // about SFINAE-enabled code will work, except of course the SFINAE.
435     template <typename A0>
436     typename boost::enable_if<
437 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
438         std::is_same<int,A0>
439 #else
440         typename boost::mpl::if_<
441             boost::is_same<int,A0>
442           , boost::mpl::true_
443           , boost::mpl::false_
444         >::type
445 #endif
446       , int
447     >::type
sfinae(A0 const & a0)448         sfinae(A0 const& a0)
449     {
450         return 0;
451     }
452 #endif  // BOOST_NO_SFINAE
453 
454     struct predicate
455     {
456         template <typename T, typename Args>
457 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
458         using fn = std::is_convertible<T,std::string>;
459 #else
460         struct apply
461           : boost::mpl::if_<
462                 boost::is_convertible<T,std::string>
463               , boost::mpl::true_
464               , boost::mpl::false_
465             >
466         {
467         };
468 #endif
469 
470         BOOST_PARAMETER_BASIC_CONST_FUNCTION_CALL_OPERATOR((bool), test::tag,
471             (required
472                 (value, *)
473                 (index, *)
474             )
475         )
476         {
477             return args[test::_value] < args[test::_index];
478         }
479     };
480 
481     BOOST_PARAMETER_FUNCTION((int), sfinae1, test::tag,
482         (required
483             (name, *(test::predicate))
484         )
485     )
486     {
487         return 1;
488     }
489 
490 #if !defined(BOOST_NO_SFINAE)
491     // On compilers that actually support SFINAE, add another overload
492     // that is an equally good match and can only be in the overload set
493     // when the others are not.  This tests that the SFINAE is actually
494     // working.  On all other compilers we're just checking that everything
495     // about SFINAE-enabled code will work, except of course the SFINAE.
496     template <typename A0>
497     typename boost::enable_if<
498 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
499         std::is_same<int,A0>
500 #else
501         typename boost::mpl::if_<
502             boost::is_same<int,A0>
503           , boost::mpl::true_
504           , boost::mpl::false_
505         >::type
506 #endif
507       , int
508     >::type
sfinae1(A0 const & a0)509         sfinae1(A0 const& a0)
510     {
511         return 0;
512     }
513 #endif  // BOOST_NO_SFINAE
514 
515     struct udt
516     {
udttest::udt517         udt(int foo_, int bar_) : foo(foo_), bar(bar_)
518         {
519         }
520 
521         int foo;
522         int bar;
523     };
524 
525     BOOST_PARAMETER_FUNCTION((int), lazy_defaults, test::tag,
526         (required
527             (name, *)
528         )
529         (optional
530             (value, *, name.foo)
531             (index, *, name.bar)
532         )
533     )
534     {
535         return 0;
536     }
537 } // namespace test
538 
539 #if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
540 #include <boost/parameter/aux_/as_lvalue.hpp>
541 #endif
542 
543 #include <boost/core/lightweight_test.hpp>
544 
main()545 int main()
546 {
547     test::f(
548         test::values(std::string("foo"), 1.f, 2)
549       , std::string("foo")
550     );
551     test::f(
552         test::_tester = test::values(std::string("foo"), 1.f, 2)
553       , test::_name = std::string("foo")
554     );
555 
556     int index_lvalue = 2;
557 
558     test::f(
559         test::_tester = test::values(std::string("foo"), 1.f, 2)
560       , test::_name = std::string("foo")
561       , test::_value = 1.f
562       , test::_index = index_lvalue
563     );
564 
565     test::f(
566         test::values(std::string("foo"), 1.f, 2)
567       , std::string("foo")
568       , 1.f
569       , index_lvalue
570     );
571 
572     test::g(
573         test::values(std::string("foo"), 1.f, 2)
574       , std::string("foo")
575       , 1.f
576 #if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
577       , boost::parameter::aux::as_lvalue(2)
578 #else
579       , 2
580 #endif
581     );
582 
583     test::h(
584         test::values(std::string("foo"), 1.f, 2)
585       , std::string("foo")
586       , 1.f
587 #if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
588       , boost::parameter::aux::as_lvalue(2)
589 #else
590       , 2
591 #endif
592     );
593 
594     test::h2(
595         test::_tester = test::values(std::string("foo"), 1.f, 2)
596       , test::_name = std::string("foo")
597       , test::_value = 1.f
598     );
599 
600     test::class_0 u;
601 
602     BOOST_TEST(2 == u.i);
603     BOOST_TEST(1.f == u.f);
604 
605     u();
606 
607     BOOST_TEST(1 == u.i);
608     BOOST_TEST(2.f == u.f);
609 
610     test::class_1 x(
611         test::values(std::string("foo"), 1.f, 2)
612       , std::string("foo")
613       , test::_index = 2
614     );
615 
616     x.f(test::values(std::string("foo"), 1.f, 2), std::string("foo"));
617     x.f(
618         test::_tester = test::values(std::string("foo"), 1.f, 2)
619       , test::_name = std::string("foo")
620     );
621     x.f2(test::values(std::string("foo"), 1.f, 2), std::string("foo"));
622     x.f2(
623         test::_tester = test::values(std::string("foo"), 1.f, 2)
624       , test::_name = std::string("foo")
625     );
626     x(test::values(std::string("foo"), 1.f, 2), std::string("foo"));
627     x(
628         test::_tester = test::values(std::string("foo"), 1.f, 2)
629       , test::_name = std::string("foo")
630     );
631 
632     test::class_1 const& x_const = x;
633 
634     x_const.f(test::values(std::string("foo"), 1.f, 2), std::string("foo"));
635     x_const.f(
636         test::_tester = test::values(std::string("foo"), 1.f, 2)
637       , test::_name = std::string("foo")
638     );
639     x_const.f2(test::values(std::string("foo"), 1.f, 2), std::string("foo"));
640     x_const.f2(
641         test::_tester = test::values(std::string("foo"), 1.f, 2)
642       , test::_name = std::string("foo")
643     );
644     test::class_1::f_static(
645         test::values(std::string("foo"), 1.f, 2)
646       , std::string("foo")
647     );
648     test::class_1::f_static(
649         test::_tester = test::values(std::string("foo"), 1.f, 2)
650       , test::_name = std::string("foo")
651     );
652     x_const(test::values(std::string("foo"), 1.f, 2), std::string("foo"));
653     x_const(
654         test::_tester = test::values(std::string("foo"), 1.f, 2)
655       , test::_name = std::string("foo")
656     );
657 
658     test::predicate p;
659     test::predicate const& p_const = p;
660 
661     BOOST_TEST(p_const(3, 4));
662     BOOST_TEST(!p_const(4, 3));
663     BOOST_TEST(!p_const(test::_index = 3, test::_value = 4));
664 
665 #if !defined(BOOST_NO_SFINAE) && \
666     !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
667     // GCC 3- tries to bind string literals
668     // to non-const references to char const*.
669     // BOOST_TEST(test::sfinae("foo") == 1);
670     char const* foo_str = "foo";
671     BOOST_TEST(test::sfinae(foo_str) == 1);
672     BOOST_TEST(test::sfinae(1) == 0);
673 
674 #if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x580))
675     // Sun actually eliminates the desired overload for some reason.
676     // Disabling this part of the test because SFINAE abilities are
677     // not the point of this test.
678     BOOST_TEST(test::sfinae1(foo_str) == 1);
679 #endif
680 
681     BOOST_TEST(test::sfinae1(1) == 0);
682 #endif
683 
684     test::lazy_defaults(test::_name = test::udt(0, 1));
685     test::lazy_defaults(test::_name = 0, test::_value = 1, test::_index = 2);
686 
687     return boost::report_errors();
688 }
689 
690