1 ///////////////////////////////////////////////////////////////////////////////
3 // Copyright David Abrahams 2002, Joel de Guzman, 2002.
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
8 ///////////////////////////////////////////////////////////////////////////////
9 #ifndef INIT_JDG20020820_HPP
10 #define INIT_JDG20020820_HPP
12 # include <boost/python/detail/prefix.hpp>
14 #include <boost/python/detail/type_list.hpp>
15 #include <boost/python/args_fwd.hpp>
16 #include <boost/python/detail/make_keyword_range_fn.hpp>
17 #include <boost/python/def_visitor.hpp>
19 #include <boost/mpl/if.hpp>
20 #include <boost/mpl/eval_if.hpp>
21 #include <boost/mpl/size.hpp>
22 #include <boost/mpl/iterator_range.hpp>
23 #include <boost/mpl/empty.hpp>
24 #include <boost/mpl/begin_end.hpp>
25 #include <boost/mpl/bool.hpp>
26 #include <boost/mpl/prior.hpp>
27 #include <boost/mpl/joint_view.hpp>
28 #include <boost/mpl/back.hpp>
30 #include <boost/type_traits/is_same.hpp>
32 #include <boost/preprocessor/enum_params_with_a_default.hpp>
33 #include <boost/preprocessor/enum_params.hpp>
37 ///////////////////////////////////////////////////////////////////////////////
38 #define BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT \
39 BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( \
40 BOOST_PYTHON_MAX_ARITY, \
44 #define BOOST_PYTHON_OVERLOAD_TYPES \
45 BOOST_PP_ENUM_PARAMS_Z(1, \
46 BOOST_PYTHON_MAX_ARITY, \
49 #define BOOST_PYTHON_OVERLOAD_ARGS \
50 BOOST_PP_ENUM_PARAMS_Z(1, \
51 BOOST_PYTHON_MAX_ARITY, \
54 ///////////////////////////////////////////////////////////////////////////////
55 namespace boost
{ namespace python
{
57 template <BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT
>
58 class init
; // forward declaration
61 template <BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT
>
62 struct optional
; // forward declaration
68 template <int keywords
, int init_args
>
69 struct more_keywords_than_init_arguments
71 typedef char too_many_keywords
[init_args
- keywords
>= 0 ? 1 : -1];
75 // is_optional<T>::value
77 // This metaprogram checks if T is an optional
79 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
86 template <BOOST_PYTHON_OVERLOAD_TYPES
>
87 static boost::type_traits::yes_type
f(optional
<BOOST_PYTHON_OVERLOAD_ARGS
>);
88 static boost::type_traits::no_type
f(...);
93 BOOST_STATIC_CONSTANT(
95 sizeof(f(t())) == sizeof(::boost::type_traits::yes_type
));
96 typedef mpl::bool_
<value
> type
;
106 template <BOOST_PYTHON_OVERLOAD_TYPES
>
107 struct is_optional
<optional
<BOOST_PYTHON_OVERLOAD_ARGS
> >
113 template <int NDefaults
>
114 struct define_class_init_helper
;
116 } // namespace detail
118 template <class DerivedT
>
119 struct init_base
: def_visitor
<DerivedT
>
121 init_base(char const* doc_
, detail::keyword_range
const& keywords_
)
122 : m_doc(doc_
), m_keywords(keywords_
)
125 init_base(char const* doc_
)
129 DerivedT
const& derived() const
131 return *static_cast<DerivedT
const*>(this);
134 char const* doc_string() const
139 detail::keyword_range
const& keywords() const
144 static default_call_policies
call_policies()
146 return default_call_policies();
152 // Defines a set of n_defaults + 1 constructors for its
153 // class_<...> argument. Each constructor after the first has
154 // one less argument to its right. Example:
156 // init<int, optional<char, long, double> >
160 // __init__(int, char, long, double)
161 // __init__(int, char, long)
162 // __init__(int, char)
164 template <class classT
>
165 void visit(classT
& cl
) const
167 typedef typename
DerivedT::signature signature
;
168 typedef typename
DerivedT::n_arguments n_arguments
;
169 typedef typename
DerivedT::n_defaults n_defaults
;
171 detail::define_class_init_helper
<n_defaults::value
>::apply(
173 , derived().call_policies()
176 , derived().doc_string()
177 , derived().keywords());
180 friend class python::def_visitor_access
;
182 private: // data members
184 detail::keyword_range m_keywords
;
187 template <class CallPoliciesT
, class InitT
>
188 class init_with_call_policies
189 : public init_base
<init_with_call_policies
<CallPoliciesT
, InitT
> >
191 typedef init_base
<init_with_call_policies
<CallPoliciesT
, InitT
> > base
;
193 typedef typename
InitT::n_arguments n_arguments
;
194 typedef typename
InitT::n_defaults n_defaults
;
195 typedef typename
InitT::signature signature
;
197 init_with_call_policies(
198 CallPoliciesT
const& policies_
200 , detail::keyword_range
const& keywords
202 : base(doc_
, keywords
)
203 , m_policies(policies_
)
206 CallPoliciesT
const& call_policies() const
208 return this->m_policies
;
211 private: // data members
212 CallPoliciesT m_policies
;
216 // drop1<S> is the initial length(S) elements of S
222 : mpl::iterator_range
<
223 typename
mpl::begin
<S
>::type
224 , typename
mpl::prior
<
225 typename
mpl::end
<S
>::type
231 template <BOOST_PYTHON_OVERLOAD_TYPES
>
232 class init
: public init_base
<init
<BOOST_PYTHON_OVERLOAD_ARGS
> >
234 typedef init_base
<init
<BOOST_PYTHON_OVERLOAD_ARGS
> > base
;
236 typedef init
<BOOST_PYTHON_OVERLOAD_ARGS
> self_t
;
238 init(char const* doc_
= 0)
243 template <std::size_t N
>
244 init(char const* doc_
, detail::keywords
<N
> const& kw
)
245 : base(doc_
, kw
.range())
247 typedef typename
detail::error::more_keywords_than_init_arguments
<
248 N
, n_arguments::value
+ 1
249 >::too_many_keywords assertion
;
252 template <std::size_t N
>
253 init(detail::keywords
<N
> const& kw
, char const* doc_
= 0)
254 : base(doc_
, kw
.range())
256 typedef typename
detail::error::more_keywords_than_init_arguments
<
257 N
, n_arguments::value
+ 1
258 >::too_many_keywords assertion
;
261 template <class CallPoliciesT
>
262 init_with_call_policies
<CallPoliciesT
, self_t
>
263 operator[](CallPoliciesT
const& policies
) const
265 return init_with_call_policies
<CallPoliciesT
, self_t
>(
266 policies
, this->doc_string(), this->keywords());
269 typedef detail::type_list
<BOOST_PYTHON_OVERLOAD_ARGS
> signature_
;
271 typedef detail::is_optional
<
272 typename
mpl::eval_if
<
273 mpl::empty
<signature_
>
275 , mpl::back
<signature_
>
279 typedef typename
mpl::eval_if
<
281 , mpl::back
<signature_
>
283 >::type optional_args
;
285 typedef typename
mpl::eval_if
<
288 mpl::empty
<optional_args
>
289 , detail::drop1
<signature_
>
291 detail::drop1
<signature_
>
298 // TODO: static assert to make sure there are no other optional elements
300 // Count the number of default args
301 typedef mpl::size
<optional_args
> n_defaults
;
302 typedef mpl::size
<signature
> n_arguments
;
305 ///////////////////////////////////////////////////////////////////////////////
309 // optional<T0...TN>::type returns a typelist.
311 ///////////////////////////////////////////////////////////////////////////////
312 template <BOOST_PYTHON_OVERLOAD_TYPES
>
314 : detail::type_list
<BOOST_PYTHON_OVERLOAD_ARGS
>
320 template <class ClassT
, class CallPoliciesT
, class Signature
, class NArgs
>
321 inline void def_init_aux(
325 , CallPoliciesT
const& policies
327 , detail::keyword_range
const& keywords_
332 , detail::make_keyword_range_constructor
<Signature
,NArgs
>(
335 , (typename
ClassT::metadata::holder
*)0
341 ///////////////////////////////////////////////////////////////////////////////
343 // define_class_init_helper<N>::apply
347 // Accepts a class_ and an arguments list. Defines a constructor
348 // for the class given the arguments and recursively calls
349 // define_class_init_helper<N-1>::apply with one fewer argument (the
350 // rightmost argument is shaved off)
352 ///////////////////////////////////////////////////////////////////////////////
353 template <int NDefaults
>
354 struct define_class_init_helper
357 template <class ClassT
, class CallPoliciesT
, class Signature
, class NArgs
>
360 , CallPoliciesT
const& policies
361 , Signature
const& args
364 , detail::keyword_range keywords
)
366 detail::def_init_aux(cl
, args
, NArgs(), policies
, doc
, keywords
);
368 if (keywords
.second
> keywords
.first
)
371 typedef typename
mpl::prior
<NArgs
>::type next_nargs
;
372 define_class_init_helper
<NDefaults
-1>::apply(
373 cl
, policies
, Signature(), next_nargs(), doc
, keywords
);
377 ///////////////////////////////////////////////////////////////////////////////
379 // define_class_init_helper<0>::apply
383 // Accepts a class_ and an arguments list. Defines a constructor
384 // for the class given the arguments.
386 ///////////////////////////////////////////////////////////////////////////////
388 struct define_class_init_helper
<0> {
390 template <class ClassT
, class CallPoliciesT
, class Signature
, class NArgs
>
393 , CallPoliciesT
const& policies
394 , Signature
const& args
397 , detail::keyword_range
const& keywords
)
399 detail::def_init_aux(cl
, args
, NArgs(), policies
, doc
, keywords
);
404 }} // namespace boost::python
406 #undef BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT
407 #undef BOOST_PYTHON_OVERLOAD_TYPES
408 #undef BOOST_PYTHON_OVERLOAD_ARGS
409 #undef BOOST_PYTHON_IS_OPTIONAL_VALUE
410 #undef BOOST_PYTHON_APPEND_TO_INIT
412 ///////////////////////////////////////////////////////////////////////////////
413 #endif // INIT_JDG20020820_HPP