1 // Copyright Cromwell D. Enage 2017.
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 
8 #if (BOOST_PARAMETER_MAX_ARITY < 4)
9 #error Define BOOST_PARAMETER_MAX_ARITY as 4 or greater.
10 #endif
11 #if !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING) && \
12     (BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY < 5)
13 #error Define BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY \
14 as 5 or greater.
15 #endif
16 
17 #include <boost/parameter/name.hpp>
18 
19 namespace test {
20 
21     BOOST_PARAMETER_NAME((_lrc0, keywords) in(lrc0))
22     BOOST_PARAMETER_NAME((_lr0, keywords) in_out(lr0))
23     BOOST_PARAMETER_NAME((_rrc0, keywords) in(rrc0))
24 #if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
25     BOOST_PARAMETER_NAME((_rr0, keywords) consume(rr0))
26 #else
27     BOOST_PARAMETER_NAME((_rr0, keywords) rr0)
28 #endif
29 } // namespace test
30 
31 #include <boost/parameter/parameters.hpp>
32 #include <boost/parameter/required.hpp>
33 
34 namespace test {
35 
36     struct f_parameters
37       : boost::parameter::parameters<
38             boost::parameter::required<test::keywords::lrc0>
39           , boost::parameter::required<test::keywords::lr0>
40           , boost::parameter::required<test::keywords::rrc0>
41           , boost::parameter::required<test::keywords::rr0>
42         >
43     {
44     };
45 } // namespace test
46 
47 #include <boost/core/lightweight_test.hpp>
48 #include "evaluate_category.hpp"
49 
50 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
51 #include <type_traits>
52 #else
53 #include <boost/type_traits/is_scalar.hpp>
54 #endif
55 
56 namespace test {
57 
58     template <typename T>
59     struct B
60     {
61         template <typename Args>
evaluatetest::B62         static void evaluate(Args const& args)
63         {
64             BOOST_TEST_EQ(
65                 test::passed_by_lvalue_reference_to_const
66               , test::A<T>::evaluate_category(args[test::_lrc0])
67             );
68             BOOST_TEST_EQ(
69                 test::passed_by_lvalue_reference
70               , test::A<T>::evaluate_category(args[test::_lr0])
71             );
72 #if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
73 
74 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
75             if (std::is_scalar<T>::value)
76 #else
77             if (boost::is_scalar<T>::value)
78 #endif
79             {
80                 BOOST_TEST_EQ(
81                     test::passed_by_lvalue_reference_to_const
82                   , test::A<T>::evaluate_category(args[test::_rrc0])
83                 );
84                 BOOST_TEST_EQ(
85                     test::passed_by_lvalue_reference_to_const
86                   , test::A<T>::evaluate_category(args[test::_rr0])
87                 );
88             }
89             else
90             {
91                 BOOST_TEST_EQ(
92                     test::passed_by_rvalue_reference_to_const
93                   , test::A<T>::evaluate_category(args[test::_rrc0])
94                 );
95                 BOOST_TEST_EQ(
96                     test::passed_by_rvalue_reference
97                   , test::A<T>::evaluate_category(args[test::_rr0])
98                 );
99             }
100 #else   // !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
101             BOOST_TEST_EQ(
102                 test::passed_by_lvalue_reference_to_const
103               , test::A<T>::evaluate_category(args[test::_rrc0])
104             );
105             BOOST_TEST_EQ(
106                 test::passed_by_lvalue_reference_to_const
107               , test::A<T>::evaluate_category(args[test::_rr0])
108             );
109 #endif  // BOOST_PARAMETER_HAS_PERFECT_FORWARDING
110         }
111     };
112 } // namespace test
113 
114 #include <boost/parameter/deduced.hpp>
115 #include <boost/mpl/bool.hpp>
116 #include <boost/mpl/placeholders.hpp>
117 #include <boost/mpl/if.hpp>
118 #include <boost/type_traits/is_convertible.hpp>
119 
120 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
121 #include <boost/mp11/bind.hpp>
122 #endif
123 
124 namespace test {
125 
126     struct e_parameters
127       : boost::parameter::parameters<
128             boost::parameter::required<
129                 boost::parameter::deduced<test::keywords::lrc0>
130 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
131               , boost::mp11::mp_bind<
132                     std::is_convertible
133                   , boost::mp11::_1
134                   , float
135                 >
136 #else
137               , boost::mpl::if_<
138                     boost::is_convertible<boost::mpl::_1,float>
139                   , boost::mpl::true_
140                   , boost::mpl::false_
141                 >
142 #endif
143             >
144           , boost::parameter::required<
145                 boost::parameter::deduced<test::keywords::lr0>
146               , boost::mpl::if_<
147                     boost::is_convertible<boost::mpl::_1,char const*>
148                   , boost::mpl::true_
149                   , boost::mpl::false_
150                 >
151             >
152           , boost::parameter::required<
153                 boost::parameter::deduced<test::keywords::rr0>
154               , test::string_predicate<test::keywords::lr0>
155             >
156         >
157     {
158     };
159 } // namespace test
160 
161 #include <boost/parameter/value_type.hpp>
162 
163 #if !defined(BOOST_PARAMETER_CAN_USE_MP11)
164 #include <boost/type_traits/remove_const.hpp>
165 #endif
166 
167 namespace test {
168 
169     struct E
170     {
171         template <typename Args>
evaluatetest::E172         static void evaluate(Args const& args)
173         {
174 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
175             BOOST_TEST((
176                 test::passed_by_lvalue_reference_to_const == test::A<
177                     typename std::remove_const<
178                         typename boost::parameter::value_type<
179                             Args
180                           , test::keywords::lrc0
181                         >::type
182                     >::type
183                 >::evaluate_category(args[test::_lrc0])
184             ));
185             BOOST_TEST((
186                 test::passed_by_lvalue_reference == test::A<
187                     typename std::remove_const<
188                         typename boost::parameter::value_type<
189                             Args
190                           , test::keywords::lr0
191                         >::type
192                     >::type
193                 >::evaluate_category(args[test::_lr0])
194             ));
195 #else   // !defined(BOOST_PARAMETER_CAN_USE_MP11)
196             BOOST_TEST((
197                 test::passed_by_lvalue_reference_to_const == test::A<
198                     typename boost::remove_const<
199                         typename boost::parameter::value_type<
200                             Args
201                           , test::keywords::lrc0
202                         >::type
203                     >::type
204                 >::evaluate_category(args[test::_lrc0])
205             ));
206             BOOST_TEST((
207                 test::passed_by_lvalue_reference == test::A<
208                     typename boost::remove_const<
209                         typename boost::parameter::value_type<
210                             Args
211                           , test::keywords::lr0
212                         >::type
213                     >::type
214                 >::evaluate_category(args[test::_lr0])
215             ));
216 #endif  // BOOST_PARAMETER_CAN_USE_MP11
217 
218 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
219             BOOST_TEST((
220                 test::passed_by_rvalue_reference == test::A<
221                     typename std::remove_const<
222                         typename boost::parameter::value_type<
223                             Args
224                           , test::keywords::rr0
225                         >::type
226                     >::type
227                 >::evaluate_category(args[test::_rr0])
228             ));
229 #elif defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
230             BOOST_TEST((
231                 test::passed_by_rvalue_reference == test::A<
232                     typename boost::remove_const<
233                         typename boost::parameter::value_type<
234                             Args
235                           , test::keywords::rr0
236                         >::type
237                     >::type
238                 >::evaluate_category(args[test::_rr0])
239             ));
240 #else   // no MP11 or perfect forwarding support
241             BOOST_TEST((
242                 test::passed_by_lvalue_reference_to_const == test::A<
243                     typename boost::remove_const<
244                         typename boost::parameter::value_type<
245                             Args
246                           , test::keywords::rr0
247                         >::type
248                     >::type
249                 >::evaluate_category(args[test::_rr0])
250             ));
251 #endif  // MP11 or perfect forwarding support
252         }
253     };
254 } // namespace test
255 
main()256 int main()
257 {
258     test::B<float>::evaluate(
259         test::f_parameters()(
260             test::lvalue_const_float()
261           , test::lvalue_float()
262           , test::rvalue_const_float()
263           , test::rvalue_float()
264         )
265     );
266     test::B<char const*>::evaluate(
267         test::f_parameters()(
268             test::lvalue_const_char_ptr()
269           , test::lvalue_char_ptr()
270           , test::rvalue_const_char_ptr()
271           , test::rvalue_char_ptr()
272         )
273     );
274     test::B<std::string>::evaluate(
275         test::f_parameters()(
276             test::lvalue_const_str()
277           , test::lvalue_str()
278           , test::rvalue_const_str()
279           , test::rvalue_str()
280         )
281     );
282     test::B<float>::evaluate((
283         test::_lr0 = test::lvalue_float()
284       , test::_rrc0 = test::rvalue_const_float()
285       , test::_rr0 = test::rvalue_float()
286       , test::_lrc0 = test::lvalue_const_float()
287     ));
288     test::B<char const*>::evaluate((
289         test::_lr0 = test::lvalue_char_ptr()
290       , test::_rrc0 = test::rvalue_const_char_ptr()
291       , test::_rr0 = test::rvalue_char_ptr()
292       , test::_lrc0 = test::lvalue_const_char_ptr()
293     ));
294     test::B<std::string>::evaluate((
295         test::_lr0 = test::lvalue_str()
296       , test::_rrc0 = test::rvalue_const_str()
297       , test::_rr0 = test::rvalue_str()
298       , test::_lrc0 = test::lvalue_const_str()
299     ));
300 
301     char baz_arr[4] = "qux";
302     typedef char char_arr[4];
303 
304 #if !defined(LIBS_PARAMETER_TEST_COMPILE_FAILURE_VENDOR_SPECIFIC) && \
305     BOOST_WORKAROUND(BOOST_MSVC, >= 1800)
306     // MSVC-12+ treats static_cast<char_arr&&>(baz_arr) as an lvalue.
307 #else
308     test::B<char_arr>::evaluate(
309         test::f_parameters()(
310             "crg"
311           , baz_arr
312 #if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
313           , static_cast<char_arr const&&>("uir")
314           , static_cast<char_arr&&>(baz_arr)
315 #else
316           , "grl"
317           , "grp"
318 #endif
319         )
320     );
321     test::B<char_arr>::evaluate((
322         test::_lr0 = baz_arr
323 #if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
324       , test::_rrc0 = static_cast<char_arr const&&>("wld")
325       , test::_rr0 = static_cast<char_arr&&>(baz_arr)
326 #else
327       , test::_rrc0 = "frd"
328       , test::_rr0 = "plg"
329 #endif
330       , test::_lrc0 = "mos"
331     ));
332 #endif  // MSVC-12+
333 
334     test::E::evaluate(
335         test::e_parameters()(
336             test::lvalue_char_ptr()
337           , test::rvalue_str()
338           , test::lvalue_const_float()
339         )
340     );
341     test::E::evaluate(
342         test::e_parameters()(
343             test::rvalue_str()
344           , test::lvalue_const_float()
345           , test::lvalue_char_ptr()
346         )
347     );
348     return boost::report_errors();
349 }
350 
351