1 // Copyright Cromwell D. Enage 2018.
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 #ifndef BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_NO_SPEC_OVERLOADS_HPP
7 #define BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_NO_SPEC_OVERLOADS_HPP
8 
9 #include <boost/parameter/aux_/preprocessor/impl/function_name.hpp>
10 
11 // Defines the no-spec implementation function header.
12 #define BOOST_PARAMETER_NO_SPEC_FUNCTION_IMPL_HEAD(name, is_const)           \
13     template <typename ResultType, typename Args>                            \
14     BOOST_PARAMETER_MEMBER_FUNCTION_STATIC(name) ResultType                  \
15         BOOST_PARAMETER_NO_SPEC_FUNCTION_IMPL_NAME(                          \
16             name, is_const                                                   \
17         )(ResultType(*)(), Args const& args)
18 /**/
19 
20 #include <boost/parameter/config.hpp>
21 
22 #if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
23 
24 #include <boost/parameter/aux_/preprocessor/impl/parenthesized_return_type.hpp>
25 
26 // Expands to the result metafunction for the specified no-spec function.
27 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
28 #define BOOST_PARAMETER_NO_SPEC_FUNCTION_HEAD(result, name, is_const)        \
29     template <typename TaggedArg0, typename ...TaggedArgs>                   \
30     using BOOST_PARAMETER_NO_SPEC_FUNCTION_RESULT_NAME(name, is_const)       \
31     = typename BOOST_PARAMETER_PARENTHESIZED_RETURN_TYPE(result);
32 /**/
33 #else
34 #define BOOST_PARAMETER_NO_SPEC_FUNCTION_HEAD(result, name, is_const)        \
35     template <typename TaggedArg0, typename ...TaggedArgs>                   \
36     struct BOOST_PARAMETER_NO_SPEC_FUNCTION_RESULT_NAME(name, is_const)      \
37       : BOOST_PARAMETER_PARENTHESIZED_RETURN_TYPE(result)                    \
38     {                                                                        \
39     };
40 /**/
41 #endif  // BOOST_PARAMETER_CAN_USE_MP11
42 
43 #include <boost/parameter/compose.hpp>
44 #include <boost/parameter/are_tagged_arguments.hpp>
45 #include <boost/parameter/aux_/preprocessor/impl/parenthesized_type.hpp>
46 #include <boost/core/enable_if.hpp>
47 
48 // Exapnds to a variadic constructor that is enabled if and only if all its
49 // arguments are tagged arguments.  The enclosing class must inherit from the
50 // specified base class, which in turn must implement a constructor that takes
51 // in the argument pack that this one passes on.
52 #define BOOST_PARAMETER_NO_SPEC_CONSTRUCTOR(class_, base)                    \
53     template <                                                               \
54         typename TaggedArg0                                                  \
55       , typename ...TaggedArgs                                               \
56       , typename = typename ::boost::enable_if<                              \
57             ::boost::parameter                                               \
58             ::are_tagged_arguments<TaggedArg0,TaggedArgs...>                 \
59         >::type                                                              \
60     > inline explicit                                                        \
61     class_(TaggedArg0 const& arg0, TaggedArgs const&... args)                \
62       : BOOST_PARAMETER_PARENTHESIZED_TYPE(base)(                            \
63             ::boost::parameter::compose(arg0, args...)                       \
64         )                                                                    \
65     {                                                                        \
66     }
67 /**/
68 
69 // Exapnds to a variadic constructor that is enabled if and only if all its
70 // arguments are tagged arguments.  The specified function must be able to
71 // take in the argument pack that this constructor passes on.
72 #define BOOST_PARAMETER_NO_SPEC_NO_BASE_CONSTRUCTOR(class_, func)            \
73     template <                                                               \
74         typename TaggedArg0                                                  \
75       , typename ...TaggedArgs                                               \
76       , typename = typename ::boost::enable_if<                              \
77             ::boost::parameter                                               \
78             ::are_tagged_arguments<TaggedArg0,TaggedArgs...>                 \
79         >::type                                                              \
80     > inline explicit                                                        \
81     class_(TaggedArg0 const& arg0, TaggedArgs const&... args)                \
82     {                                                                        \
83         func(::boost::parameter::compose(arg0, args...));                    \
84     }
85 /**/
86 
87 #include <boost/parameter/aux_/preprocessor/nullptr.hpp>
88 #include <boost/preprocessor/control/expr_if.hpp>
89 
90 // Exapnds to a variadic function that is enabled if and only if
91 // all its arguments are tagged arguments.
92 #define BOOST_PARAMETER_NO_SPEC_FUNCTION_OVERLOAD(name, impl, is_m, c)       \
93     template <typename TaggedArg0, typename ...TaggedArgs>                   \
94     BOOST_PARAMETER_MEMBER_FUNCTION_STATIC(impl)                             \
95     inline typename ::boost::lazy_enable_if<                                 \
96         ::boost::parameter                                                   \
97         ::are_tagged_arguments<TaggedArg0,TaggedArgs...>                     \
98       , BOOST_PARAMETER_NO_SPEC_FUNCTION_RESULT_NAME(                        \
99             impl, c                                                          \
100         )<TaggedArg0,TaggedArgs...>                                          \
101     >::type BOOST_PARAMETER_MEMBER_FUNCTION_NAME(name)                       \
102     (TaggedArg0 const& arg0, TaggedArgs const&... args)                      \
103     BOOST_PP_EXPR_IF(c, const)                                               \
104     {                                                                        \
105         return BOOST_PP_EXPR_IF(is_m, this->)                                \
106         BOOST_PARAMETER_NO_SPEC_FUNCTION_IMPL_NAME(impl, c)(                 \
107             static_cast<                                                     \
108                 typename BOOST_PARAMETER_NO_SPEC_FUNCTION_RESULT_NAME(       \
109                     impl, c                                                  \
110                 )<TaggedArg0,TaggedArgs...>::type(*)()                       \
111             >(BOOST_PARAMETER_AUX_PP_NULLPTR)                                \
112           , ::boost::parameter::compose(arg0, args...)                       \
113         );                                                                   \
114     }
115 /**/
116 
117 #else   // !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
118 
119 #include <boost/parameter/aux_/void.hpp>
120 #include <boost/parameter/aux_/preprocessor/impl/parenthesized_return_type.hpp>
121 #include <boost/preprocessor/facilities/intercept.hpp>
122 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
123 
124 // Expands to the result metafunction for the specified no-spec function.
125 #define BOOST_PARAMETER_NO_SPEC_FUNCTION_HEAD(result, name, is_const)        \
126     template <                                                               \
127         BOOST_PP_ENUM_BINARY_PARAMS(                                         \
128             BOOST_PARAMETER_COMPOSE_MAX_ARITY                                \
129           , typename TaggedArg                                               \
130           , = ::boost::parameter::void_ BOOST_PP_INTERCEPT                   \
131         )                                                                    \
132     >                                                                        \
133     struct BOOST_PARAMETER_NO_SPEC_FUNCTION_RESULT_NAME(name, is_const)      \
134       : BOOST_PARAMETER_PARENTHESIZED_RETURN_TYPE(result)                    \
135     {                                                                        \
136     };
137 /**/
138 
139 #include <boost/parameter/compose.hpp>
140 #include <boost/parameter/aux_/preprocessor/impl/parenthesized_type.hpp>
141 #include <boost/preprocessor/comparison/equal.hpp>
142 #include <boost/preprocessor/control/expr_if.hpp>
143 #include <boost/preprocessor/repetition/enum_params.hpp>
144 #include <boost/preprocessor/tuple/elem.hpp>
145 
146 #if defined(BOOST_NO_SFINAE)
147 
148 // Exapnds to a tagged-argument constructor overload that passes the argument
149 // pack to the base class delegate constructor.
150 #define BOOST_PARAMETER_NO_SPEC_CONSTRUCTOR_OVERLOAD_Z(z, n, data)           \
151     template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename TaggedArg)>              \
152     BOOST_PP_EXPR_IF(BOOST_PP_EQUAL(n, 1), explicit) inline                  \
153     BOOST_PP_TUPLE_ELEM(2, 0, data)(                                         \
154         BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, TaggedArg, const& arg)           \
155     ) : BOOST_PARAMETER_PARENTHESIZED_TYPE(BOOST_PP_TUPLE_ELEM(2, 1, data))( \
156             ::boost::parameter::compose(BOOST_PP_ENUM_PARAMS_Z(z, n, arg))   \
157         )                                                                    \
158     {                                                                        \
159     }
160 /**/
161 
162 // Exapnds to a tagged-argument constructor overload that passes the argument
163 // pack to the delegate function.
164 #define BOOST_PARAMETER_NO_SPEC_NO_BASE_CONSTRUCTOR_OVERLOAD_Z(z, n, data)   \
165     template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename TaggedArg)>              \
166     BOOST_PP_EXPR_IF(BOOST_PP_EQUAL(n, 1), explicit) inline                  \
167     BOOST_PP_TUPLE_ELEM(2, 0, data)(                                         \
168         BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, TaggedArg, const& a)             \
169     )                                                                        \
170     {                                                                        \
171         BOOST_PP_TUPLE_ELEM(2, 1, data)(                                     \
172             ::boost::parameter::compose(BOOST_PP_ENUM_PARAMS_Z(z, n, a))     \
173         );                                                                   \
174     }
175 /**/
176 
177 #include <boost/parameter/aux_/preprocessor/nullptr.hpp>
178 
179 // Exapnds to a tagged-argument function overload.
180 #define BOOST_PARAMETER_NO_SPEC_FUNCTION_OVERLOAD_Z(z, n, data)              \
181     template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename TaggedArg)>              \
182     BOOST_PARAMETER_MEMBER_FUNCTION_STATIC(BOOST_PP_TUPLE_ELEM(4, 1, data))  \
183     inline typename BOOST_PARAMETER_NO_SPEC_FUNCTION_RESULT_NAME(            \
184         BOOST_PP_TUPLE_ELEM(4, 1, data)                                      \
185       , BOOST_PP_TUPLE_ELEM(4, 3, data)                                      \
186     )<BOOST_PP_ENUM_PARAMS_Z(z, n, TaggedArg)>::type                         \
187         BOOST_PARAMETER_MEMBER_FUNCTION_NAME(                                \
188             BOOST_PP_TUPLE_ELEM(4, 0, data)                                  \
189         )(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, TaggedArg, const& arg))        \
190         BOOST_PP_EXPR_IF(BOOST_PP_TUPLE_ELEM(4, 3, data), const)             \
191     {                                                                        \
192         return BOOST_PP_EXPR_IF(BOOST_PP_TUPLE_ELEM(4, 2, data), this->)     \
193         BOOST_PARAMETER_NO_SPEC_FUNCTION_IMPL_NAME(                          \
194             BOOST_PP_TUPLE_ELEM(4, 1, data)                                  \
195           , BOOST_PP_TUPLE_ELEM(4, 3, data)                                  \
196         )(                                                                   \
197             static_cast<                                                     \
198                 typename BOOST_PARAMETER_NO_SPEC_FUNCTION_RESULT_NAME(       \
199                     BOOST_PP_TUPLE_ELEM(4, 1, data)                          \
200                   , BOOST_PP_TUPLE_ELEM(4, 3, data)                          \
201                 )<BOOST_PP_ENUM_PARAMS_Z(z, n, TaggedArg)>::type(*)()        \
202             >(BOOST_PARAMETER_AUX_PP_NULLPTR)                                \
203           , ::boost::parameter::compose(BOOST_PP_ENUM_PARAMS_Z(z, n, arg))   \
204         );                                                                   \
205     }
206 /**/
207 
208 #else   // !defined(BOOST_NO_SFINAE)
209 
210 #include <boost/parameter/are_tagged_arguments.hpp>
211 #include <boost/parameter/aux_/preprocessor/nullptr.hpp>
212 #include <boost/core/enable_if.hpp>
213 
214 // Exapnds to a tagged-argument constructor overload that passes the argument
215 // pack to the base class delegate constructor.  This constructor is enabled
216 // if and only if all its arguments are tagged arguments.
217 #define BOOST_PARAMETER_NO_SPEC_CONSTRUCTOR_OVERLOAD_Z(z, n, data)           \
218     template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename TaggedArg)>              \
219     BOOST_PP_EXPR_IF(BOOST_PP_EQUAL(n, 1), explicit) inline                  \
220     BOOST_PP_TUPLE_ELEM(2, 0, data)(                                         \
221         BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, TaggedArg, const& arg)           \
222       , typename ::boost::enable_if<                                         \
223             ::boost::parameter::are_tagged_arguments<                        \
224                 BOOST_PP_ENUM_PARAMS_Z(z, n, TaggedArg)                      \
225             >                                                                \
226         >::type* = BOOST_PARAMETER_AUX_PP_NULLPTR                            \
227     ) : BOOST_PARAMETER_PARENTHESIZED_TYPE(BOOST_PP_TUPLE_ELEM(2, 1, data))( \
228             ::boost::parameter::compose(BOOST_PP_ENUM_PARAMS_Z(z, n, arg))   \
229         )                                                                    \
230     {                                                                        \
231     }
232 /**/
233 
234 // Exapnds to a tagged-argument constructor overload that passes the argument
235 // pack to the delegate function.  This constructor is enabled if and only if
236 // all its arguments are tagged arguments.
237 #define BOOST_PARAMETER_NO_SPEC_NO_BASE_CONSTRUCTOR_OVERLOAD_Z(z, n, data)   \
238     template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename TaggedArg)>              \
239     BOOST_PP_EXPR_IF(BOOST_PP_EQUAL(n, 1), explicit) inline                  \
240     BOOST_PP_TUPLE_ELEM(2, 0, data)(                                         \
241         BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, TaggedArg, const& a)             \
242       , typename ::boost::enable_if<                                         \
243             ::boost::parameter::are_tagged_arguments<                        \
244                 BOOST_PP_ENUM_PARAMS_Z(z, n, TaggedArg)                      \
245             >                                                                \
246         >::type* = BOOST_PARAMETER_AUX_PP_NULLPTR                            \
247     )                                                                        \
248     {                                                                        \
249         BOOST_PP_TUPLE_ELEM(2, 1, data)(                                     \
250             ::boost::parameter::compose(BOOST_PP_ENUM_PARAMS_Z(z, n, a))     \
251         );                                                                   \
252     }
253 /**/
254 
255 // Exapnds to a function overload that is enabled if and only if
256 // all its arguments are tagged arguments.
257 #define BOOST_PARAMETER_NO_SPEC_FUNCTION_OVERLOAD_Z(z, n, data)              \
258     template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename TaggedArg)>              \
259     BOOST_PARAMETER_MEMBER_FUNCTION_STATIC(BOOST_PP_TUPLE_ELEM(4, 1, data))  \
260     inline typename ::boost::lazy_enable_if<                                 \
261         ::boost::parameter                                                   \
262         ::are_tagged_arguments<BOOST_PP_ENUM_PARAMS_Z(z, n, TaggedArg)>      \
263       , BOOST_PARAMETER_NO_SPEC_FUNCTION_RESULT_NAME(                        \
264             BOOST_PP_TUPLE_ELEM(4, 1, data)                                  \
265           , BOOST_PP_TUPLE_ELEM(4, 3, data)                                  \
266         )<BOOST_PP_ENUM_PARAMS_Z(z, n, TaggedArg)>                           \
267     >::type BOOST_PARAMETER_MEMBER_FUNCTION_NAME(                            \
268         BOOST_PP_TUPLE_ELEM(4, 0, data)                                      \
269     )(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, TaggedArg, const& arg))            \
270     BOOST_PP_EXPR_IF(BOOST_PP_TUPLE_ELEM(4, 3, data), const)                 \
271     {                                                                        \
272         return BOOST_PP_EXPR_IF(BOOST_PP_TUPLE_ELEM(4, 2, data), this->)     \
273         BOOST_PARAMETER_NO_SPEC_FUNCTION_IMPL_NAME(                          \
274             BOOST_PP_TUPLE_ELEM(4, 1, data)                                  \
275           , BOOST_PP_TUPLE_ELEM(4, 3, data)                                  \
276         )(                                                                   \
277             static_cast<                                                     \
278                 typename BOOST_PARAMETER_NO_SPEC_FUNCTION_RESULT_NAME(       \
279                     BOOST_PP_TUPLE_ELEM(4, 1, data)                          \
280                   , BOOST_PP_TUPLE_ELEM(4, 3, data)                          \
281                 )<BOOST_PP_ENUM_PARAMS_Z(z, n, TaggedArg)>::type(*)()        \
282             >(BOOST_PARAMETER_AUX_PP_NULLPTR)                                \
283           , ::boost::parameter::compose(BOOST_PP_ENUM_PARAMS_Z(z, n, arg))   \
284         );                                                                   \
285     }
286 /**/
287 
288 #endif  // BOOST_NO_SFINAE
289 
290 #include <boost/preprocessor/arithmetic/inc.hpp>
291 #include <boost/preprocessor/repetition/repeat_from_to.hpp>
292 
293 // Emulates a variadic constructor that is enabled if and only if all its
294 // arguments are tagged arguments.  The enclosing class must inherit from the
295 // specified base class, which in turn must implement a constructor that takes
296 // in the argument pack that this one passes on.
297 #define BOOST_PARAMETER_NO_SPEC_CONSTRUCTOR(class_, base)                    \
298     BOOST_PP_REPEAT_FROM_TO(                                                 \
299         1                                                                    \
300       , BOOST_PP_INC(BOOST_PARAMETER_COMPOSE_MAX_ARITY)                      \
301       , BOOST_PARAMETER_NO_SPEC_CONSTRUCTOR_OVERLOAD_Z                       \
302       , (class_, base)                                                       \
303     )
304 /**/
305 
306 // Emulates a variadic constructor that is enabled if and only if all its
307 // arguments are tagged arguments.  The specified function must be able to
308 // take in the argument pack that this constructor passes on.
309 #define BOOST_PARAMETER_NO_SPEC_NO_BASE_CONSTRUCTOR(class_, func)            \
310     BOOST_PP_REPEAT_FROM_TO(                                                 \
311         1                                                                    \
312       , BOOST_PP_INC(BOOST_PARAMETER_COMPOSE_MAX_ARITY)                      \
313       , BOOST_PARAMETER_NO_SPEC_NO_BASE_CONSTRUCTOR_OVERLOAD_Z               \
314       , (class_, func)                                                       \
315     )
316 /**/
317 
318 // Emulates a variadic function that is enabled if and only if
319 // all its arguments are tagged arguments.
320 #define BOOST_PARAMETER_NO_SPEC_FUNCTION_OVERLOAD(name, impl, is_m, c)       \
321     BOOST_PP_REPEAT_FROM_TO(                                                 \
322         1                                                                    \
323       , BOOST_PP_INC(BOOST_PARAMETER_COMPOSE_MAX_ARITY)                      \
324       , BOOST_PARAMETER_NO_SPEC_FUNCTION_OVERLOAD_Z                          \
325       , (name, impl, is_m, c)                                                \
326     )
327 /**/
328 
329 #endif  // BOOST_PARAMETER_HAS_PERFECT_FORWARDING
330 #endif  // include guard
331 
332