1414#include < boost/python/args_fwd.hpp>
1515#include < boost/python/detail/make_keyword_range_fn.hpp>
1616
17- #include < boost/mpl/fold_backward.hpp>
1817#include < boost/mpl/if.hpp>
1918#include < boost/mpl/apply_if.hpp>
20- #include < boost/mpl/at.hpp>
2119#include < boost/mpl/size.hpp>
22- #include < boost/mpl/push_front.hpp>
2320#include < boost/mpl/iterator_range.hpp>
24- #include < boost/mpl/not.hpp>
25-
26- # include < boost/python/detail/mpl_lambda.hpp>
27-
28- #include < boost/mpl/lambda.hpp>
21+ #include < boost/mpl/empty.hpp>
2922#include < boost/mpl/begin_end.hpp>
30- #include < boost/mpl/find_if.hpp>
31- #include < boost/mpl/fold.hpp>
32- #include < boost/mpl/pop_front.hpp>
3323#include < boost/mpl/bool.hpp>
24+ #include < boost/mpl/prior.hpp>
25+ #include < boost/mpl/joint_view.hpp>
26+ #include < boost/mpl/back.hpp>
3427
3528#include < boost/type_traits/is_same.hpp>
3629
37- #include < boost/static_assert.hpp>
3830#include < boost/preprocessor/enum_params_with_a_default.hpp>
3931#include < boost/preprocessor/enum_params.hpp>
40- #include < boost/preprocessor/enum_params.hpp>
41- #include < boost/preprocessor/repeat.hpp>
4232
4333#include < utility>
4434
@@ -80,14 +70,11 @@ namespace detail
8070 };
8171 }
8272
83- // /////////////////////////////////////////////////////////////////////////
84- //
85- // is_optional<T>::value
86- //
87- // This metaprogram checks if T is an optional
88- //
89- // /////////////////////////////////////////////////////////////////////////
90- #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
73+ // is_optional<T>::value
74+ //
75+ // This metaprogram checks if T is an optional
76+ //
77+ #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
9178
9279 template <class T >
9380 struct is_optional {
@@ -105,32 +92,21 @@ namespace detail
10592 bool , value =
10693 sizeof (f(t())) == sizeof (::boost::type_traits::yes_type));
10794 typedef mpl::bool_<value> type;
108-
109- BOOST_PYTHON_MPL_LAMBDA_SUPPORT (1 ,is_optional,(T))
11095 };
11196
112- // /////////////////////////////////////
113- #else // defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
97+ #else
11498
11599 template <class T >
116- struct is_optional_impl {
117-
118- BOOST_STATIC_CONSTANT (bool , value = false );
119- };
100+ struct is_optional
101+ : mpl::false_
102+ {};
120103
121104 template <BOOST_PYTHON_OVERLOAD_TYPES>
122- struct is_optional_impl <optional<BOOST_PYTHON_OVERLOAD_ARGS> > {
123-
124- BOOST_STATIC_CONSTANT (bool , value = true );
125- };
126-
127- template <class T >
128- struct is_optional : is_optional_impl<T>
129- {
130- typedef mpl::bool_<is_optional_impl<T>::value> type;
131- BOOST_PYTHON_MPL_LAMBDA_SUPPORT (1 ,is_optional,(T))
132- };
133- #endif // defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
105+ struct is_optional <optional<BOOST_PYTHON_OVERLOAD_ARGS> >
106+ : mpl::true_
107+ {};
108+
109+ #endif
134110
135111} // namespace detail
136112
@@ -176,10 +152,9 @@ class init_with_call_policies
176152{
177153 typedef init_base<init_with_call_policies<CallPoliciesT, InitT> > base;
178154 public:
179- BOOST_STATIC_CONSTANT (int , n_arguments = InitT::n_arguments);
180- BOOST_STATIC_CONSTANT (int , n_defaults = InitT::n_defaults);
181-
182- typedef typename InitT::reversed_args reversed_args;
155+ typedef typename InitT::n_arguments n_arguments;
156+ typedef typename InitT::n_defaults n_defaults;
157+ typedef typename InitT::signature signature;
183158
184159 init_with_call_policies (
185160 CallPoliciesT const & policies_
@@ -199,6 +174,22 @@ class init_with_call_policies
199174 CallPoliciesT m_policies;
200175};
201176
177+ //
178+ // drop1<S> is the initial length(S) elements of S
179+ //
180+ namespace detail
181+ {
182+ template <class S >
183+ struct drop1
184+ : mpl::iterator_range<
185+ typename mpl::begin<S>::type
186+ , typename mpl::prior<
187+ typename mpl::end<S>::type
188+ >::type
189+ >
190+ {};
191+ }
192+
202193template <BOOST_PYTHON_OVERLOAD_TYPES>
203194class init : public init_base <init<BOOST_PYTHON_OVERLOAD_ARGS> >
204195{
@@ -216,7 +207,7 @@ class init : public init_base<init<BOOST_PYTHON_OVERLOAD_ARGS> >
216207 : base(doc_, std::make_pair(kw.base(), kw.base() + Keywords::size))
217208 {
218209 typedef typename detail::error::more_keywords_than_init_arguments<
219- Keywords::size, n_arguments
210+ Keywords::size, n_arguments::value
220211 >::too_many_keywords assertion;
221212 }
222213
@@ -225,7 +216,7 @@ class init : public init_base<init<BOOST_PYTHON_OVERLOAD_ARGS> >
225216 : base(doc_, kw.range())
226217 {
227218 typedef typename detail::error::more_keywords_than_init_arguments<
228- Keywords::size, n_arguments
219+ Keywords::size, n_arguments::value
229220 >::too_many_keywords assertion;
230221 }
231222
@@ -238,51 +229,39 @@ class init : public init_base<init<BOOST_PYTHON_OVERLOAD_ARGS> >
238229 }
239230
240231 typedef detail::type_list<BOOST_PYTHON_OVERLOAD_ARGS> signature_;
241- typedef typename mpl::end<signature_>::type finish;
242-
243- // Find the optional<> element, if any
244- typedef typename mpl::find_if<
245- signature_, detail::is_optional<mpl::_>
246- >::type opt;
247232
248-
249- // Check to make sure the optional<> element, if any, is the last one
233+ typedef detail::is_optional<
234+ typename mpl::apply_if<
235+ mpl::empty<signature_>
236+ , mpl::false_
237+ , mpl::back<signature_>
238+ >::type
239+ > back_is_optional;
240+
250241 typedef typename mpl::apply_if<
251- is_same<opt,finish>
252- , mpl::identity<opt>
253- , mpl::next<opt>
254- >::type expected_finish;
255- BOOST_STATIC_ASSERT ((is_same<expected_finish, finish>::value));
242+ back_is_optional
243+ , mpl::back<signature_>
244+ , mpl::vector0<>
245+ >::type optional_args;
256246
257247 typedef typename mpl::apply_if<
258- is_same<opt,finish>
259- , mpl::list0<>
260- , opt
261- >::type optional_args;
248+ back_is_optional
249+ , mpl::if_<
250+ mpl::empty<optional_args>
251+ , detail::drop1<signature_>
252+ , mpl::joint_view<
253+ detail::drop1<signature_>
254+ , optional_args
255+ >
256+ >
257+ , signature_
258+ >::type signature;
259+
260+ // TODO: static assert to make sure there are no other optional elements
262261
263262 // Count the number of default args
264- BOOST_STATIC_CONSTANT (int , n_defaults = mpl::size<optional_args>::value);
265-
266- typedef typename mpl::iterator_range<
267- typename mpl::begin<signature_>::type
268- , opt
269- >::type required_args;
270-
271- // Build a reverse image of all the args, including optionals
272- typedef typename mpl::fold<
273- required_args
274- , mpl::list0<>
275- , mpl::push_front<>
276- >::type reversed_required;
277-
278- typedef typename mpl::fold<
279- optional_args
280- , reversed_required
281- , mpl::push_front<>
282- >::type reversed_args;
283-
284- // Count the maximum number of arguments
285- BOOST_STATIC_CONSTANT (int , n_arguments = mpl::size<reversed_args>::value);
263+ typedef mpl::size<optional_args> n_defaults;
264+ typedef mpl::size<signature> n_arguments;
286265};
287266
288267// /////////////////////////////////////////////////////////////////////////////
@@ -300,21 +279,16 @@ struct optional
300279
301280namespace detail
302281{
303- template <class ClassT , class CallPoliciesT , class ReversedArgs >
304- void def_init_reversed (
282+ template <class ClassT , class CallPoliciesT , class Signature , class NArgs >
283+ inline void def_init_aux (
305284 ClassT& cl
306- , ReversedArgs const &
285+ , Signature const &
286+ , NArgs
307287 , CallPoliciesT const & policies
308288 , char const * doc
309289 , detail::keyword_range const & keywords_
310290 )
311291 {
312- typedef typename mpl::fold<
313- ReversedArgs
314- , mpl::list0<>
315- , mpl::push_front<>
316- >::type args;
317-
318292 typedef typename ClassT::holder_selector holder_selector_t ;
319293# if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
320294 typedef typename holder_selector_t ::type selector_t ;
@@ -323,7 +297,7 @@ namespace detail
323297
324298 cl.def (
325299 " __init__" ,
326- detail::make_keyword_range_constructor<args >(
300+ detail::make_keyword_range_constructor<Signature,NArgs >(
327301 policies
328302 , keywords_
329303# if BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
@@ -345,28 +319,30 @@ namespace detail
345319 //
346320 // Accepts a class_ and an arguments list. Defines a constructor
347321 // for the class given the arguments and recursively calls
348- // define_class_init_helper<N-1>::apply with one less arguments (the
322+ // define_class_init_helper<N-1>::apply with one fewer argument (the
349323 // rightmost argument is shaved off)
350324 //
351325 // /////////////////////////////////////////////////////////////////////////////
352- template <int N >
326+ template <int NDefaults >
353327 struct define_class_init_helper {
354328
355- template <class ClassT , class CallPoliciesT , class ReversedArgs >
329+ template <class ClassT , class CallPoliciesT , class Signature , class NArgs >
356330 static void apply (
357331 ClassT& cl
358332 , CallPoliciesT const & policies
359- , ReversedArgs const & args
333+ , Signature const & args
334+ , NArgs
360335 , char const * doc
361336 , detail::keyword_range keywords)
362337 {
363- def_init_reversed (cl, args, policies, doc, keywords);
338+ detail::def_init_aux (cl, args, NArgs () , policies, doc, keywords);
364339
365340 if (keywords.second > keywords.first )
366341 --keywords.second ;
367-
368- typename mpl::pop_front<ReversedArgs>::type next;
369- define_class_init_helper<N-1 >::apply (cl, policies, next, doc, keywords);
342+
343+ typedef typename mpl::prior<NArgs>::type next_nargs;
344+ define_class_init_helper<NDefaults-1 >::apply (
345+ cl, policies, Signature (), next_nargs (), doc, keywords);
370346 }
371347 };
372348
@@ -383,15 +359,16 @@ namespace detail
383359 template <>
384360 struct define_class_init_helper <0 > {
385361
386- template <class ClassT , class CallPoliciesT , class ReversedArgs >
362+ template <class ClassT , class CallPoliciesT , class Signature , class NArgs >
387363 static void apply (
388364 ClassT& cl
389365 , CallPoliciesT const & policies
390- , ReversedArgs const & args
366+ , Signature const & args
367+ , NArgs
391368 , char const * doc
392369 , detail::keyword_range const & keywords)
393370 {
394- def_init_reversed (cl, args, policies, doc, keywords);
371+ def_init_aux (cl, args, NArgs () , policies, doc, keywords);
395372 }
396373 };
397374}
@@ -421,9 +398,12 @@ template <class ClassT, class InitT>
421398void
422399define_init (ClassT& cl, InitT const & i)
423400{
424- typedef typename InitT::reversed_args reversed_args;
425- detail::define_class_init_helper<InitT::n_defaults>::apply (
426- cl, i.call_policies (), reversed_args (), i.doc_string (), i.keywords ());
401+ typedef typename InitT::signature signature;
402+ typedef typename InitT::n_arguments n_arguments;
403+ typedef typename InitT::n_defaults n_defaults;
404+
405+ detail::define_class_init_helper<n_defaults::value>::apply (
406+ cl, i.call_policies (), signature (), n_arguments (), i.doc_string (), i.keywords ());
427407}
428408
429409}} // namespace boost::python
0 commit comments