fix doc example typo
[boost.git] / boost / python / init.hpp
blob6598fd35476e736d862c8be7fe6b8d1c4ba5f8dc
1 ///////////////////////////////////////////////////////////////////////////////
2 //
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)
7 //
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>
35 #include <utility>
37 ///////////////////////////////////////////////////////////////////////////////
38 #define BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT \
39 BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( \
40 BOOST_PYTHON_MAX_ARITY, \
41 class T, \
42 mpl::void_) \
44 #define BOOST_PYTHON_OVERLOAD_TYPES \
45 BOOST_PP_ENUM_PARAMS_Z(1, \
46 BOOST_PYTHON_MAX_ARITY, \
47 class T) \
49 #define BOOST_PYTHON_OVERLOAD_ARGS \
50 BOOST_PP_ENUM_PARAMS_Z(1, \
51 BOOST_PYTHON_MAX_ARITY, \
52 T) \
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
64 namespace detail
66 namespace error
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)
81 template <class T>
82 struct is_optional {
84 private:
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(...);
89 static T t();
91 public:
93 BOOST_STATIC_CONSTANT(
94 bool, value =
95 sizeof(f(t())) == sizeof(::boost::type_traits::yes_type));
96 typedef mpl::bool_<value> type;
99 #else
101 template <class T>
102 struct is_optional
103 : mpl::false_
106 template <BOOST_PYTHON_OVERLOAD_TYPES>
107 struct is_optional<optional<BOOST_PYTHON_OVERLOAD_ARGS> >
108 : mpl::true_
111 #endif
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_)
126 : m_doc(doc_)
129 DerivedT const& derived() const
131 return *static_cast<DerivedT const*>(this);
134 char const* doc_string() const
136 return m_doc;
139 detail::keyword_range const& keywords() const
141 return m_keywords;
144 static default_call_policies call_policies()
146 return default_call_policies();
149 private:
150 // visit
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> >
158 // Defines:
160 // __init__(int, char, long, double)
161 // __init__(int, char, long)
162 // __init__(int, char)
163 // __init__(int)
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()
174 , signature()
175 , n_arguments()
176 , derived().doc_string()
177 , derived().keywords());
180 friend class python::def_visitor_access;
182 private: // data members
183 char const* m_doc;
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;
192 public:
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_
199 , char const* doc_
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
218 namespace detail
220 template <class S>
221 struct drop1
222 : mpl::iterator_range<
223 typename mpl::begin<S>::type
224 , typename mpl::prior<
225 typename mpl::end<S>::type
226 >::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;
235 public:
236 typedef init<BOOST_PYTHON_OVERLOAD_ARGS> self_t;
238 init(char const* doc_ = 0)
239 : base(doc_)
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_>
274 , mpl::false_
275 , mpl::back<signature_>
276 >::type
277 > back_is_optional;
279 typedef typename mpl::eval_if<
280 back_is_optional
281 , mpl::back<signature_>
282 , mpl::vector0<>
283 >::type optional_args;
285 typedef typename mpl::eval_if<
286 back_is_optional
287 , mpl::if_<
288 mpl::empty<optional_args>
289 , detail::drop1<signature_>
290 , mpl::joint_view<
291 detail::drop1<signature_>
292 , optional_args
295 , signature_
296 >::type 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 ///////////////////////////////////////////////////////////////////////////////
307 // optional
309 // optional<T0...TN>::type returns a typelist.
311 ///////////////////////////////////////////////////////////////////////////////
312 template <BOOST_PYTHON_OVERLOAD_TYPES>
313 struct optional
314 : detail::type_list<BOOST_PYTHON_OVERLOAD_ARGS>
318 namespace detail
320 template <class ClassT, class CallPoliciesT, class Signature, class NArgs>
321 inline void def_init_aux(
322 ClassT& cl
323 , Signature const&
324 , NArgs
325 , CallPoliciesT const& policies
326 , char const* doc
327 , detail::keyword_range const& keywords_
330 cl.def(
331 "__init__"
332 , detail::make_keyword_range_constructor<Signature,NArgs>(
333 policies
334 , keywords_
335 , (typename ClassT::metadata::holder*)0
337 , doc
341 ///////////////////////////////////////////////////////////////////////////////
343 // define_class_init_helper<N>::apply
345 // General case
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>
358 static void apply(
359 ClassT& cl
360 , CallPoliciesT const& policies
361 , Signature const& args
362 , NArgs
363 , char const* doc
364 , detail::keyword_range keywords)
366 detail::def_init_aux(cl, args, NArgs(), policies, doc, keywords);
368 if (keywords.second > keywords.first)
369 --keywords.second;
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
381 // Terminal case
383 // Accepts a class_ and an arguments list. Defines a constructor
384 // for the class given the arguments.
386 ///////////////////////////////////////////////////////////////////////////////
387 template <>
388 struct define_class_init_helper<0> {
390 template <class ClassT, class CallPoliciesT, class Signature, class NArgs>
391 static void apply(
392 ClassT& cl
393 , CallPoliciesT const& policies
394 , Signature const& args
395 , NArgs
396 , char const* doc
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