400 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			400 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| ///////////////////////////////////////////////////////////////////////////////
 | |
| //
 | |
| // Copyright David Abrahams 2002, Joel de Guzman, 2002.
 | |
| // Distributed under the Boost Software License, Version 1.0. (See
 | |
| // accompanying file LICENSE_1_0.txt or copy at
 | |
| // http://www.boost.org/LICENSE_1_0.txt)
 | |
| //
 | |
| ///////////////////////////////////////////////////////////////////////////////
 | |
| #ifndef INIT_JDG20020820_HPP
 | |
| #define INIT_JDG20020820_HPP
 | |
| 
 | |
| # include <boost/python/detail/prefix.hpp>
 | |
| 
 | |
| #include <boost/python/detail/type_list.hpp>
 | |
| #include <boost/python/args_fwd.hpp>
 | |
| #include <boost/python/detail/make_keyword_range_fn.hpp>
 | |
| #include <boost/python/def_visitor.hpp>
 | |
| 
 | |
| #include <boost/mpl/if.hpp>
 | |
| #include <boost/mpl/eval_if.hpp>
 | |
| #include <boost/mpl/size.hpp>
 | |
| #include <boost/mpl/iterator_range.hpp>
 | |
| #include <boost/mpl/empty.hpp>
 | |
| #include <boost/mpl/begin_end.hpp>
 | |
| #include <boost/mpl/bool.hpp>
 | |
| #include <boost/mpl/prior.hpp>
 | |
| #include <boost/mpl/joint_view.hpp>
 | |
| #include <boost/mpl/back.hpp>
 | |
| 
 | |
| #include <boost/type_traits/is_same.hpp>
 | |
| 
 | |
| #include <boost/preprocessor/enum_params_with_a_default.hpp>
 | |
| #include <boost/preprocessor/enum_params.hpp>
 | |
| 
 | |
| #include <utility>
 | |
| 
 | |
| ///////////////////////////////////////////////////////////////////////////////
 | |
| #define BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT                                \
 | |
|     BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(                                        \
 | |
|         BOOST_PYTHON_MAX_ARITY,                                                 \
 | |
|         class T,                                                                \
 | |
|         mpl::void_)                                                             \
 | |
| 
 | |
| #define BOOST_PYTHON_OVERLOAD_TYPES                                             \
 | |
|     BOOST_PP_ENUM_PARAMS_Z(1,                                                   \
 | |
|         BOOST_PYTHON_MAX_ARITY,                                                 \
 | |
|         class T)                                                                \
 | |
| 
 | |
| #define BOOST_PYTHON_OVERLOAD_ARGS                                              \
 | |
|     BOOST_PP_ENUM_PARAMS_Z(1,                                                   \
 | |
|         BOOST_PYTHON_MAX_ARITY,                                                 \
 | |
|         T)                                                                      \
 | |
| 
 | |
| ///////////////////////////////////////////////////////////////////////////////
 | |
| namespace boost { namespace python {
 | |
| 
 | |
| template <BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT>
 | |
| class init; // forward declaration
 | |
| 
 | |
| 
 | |
| template <BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT>
 | |
| struct optional; // forward declaration
 | |
| 
 | |
| namespace detail
 | |
| {
 | |
|   namespace error
 | |
|   {
 | |
|     template <int keywords, int init_args>
 | |
|     struct more_keywords_than_init_arguments
 | |
|     {
 | |
|         typedef char too_many_keywords[init_args - keywords >= 0 ? 1 : -1] BOOST_ATTRIBUTE_UNUSED;
 | |
|     };
 | |
|   }
 | |
| 
 | |
|   //  is_optional<T>::value
 | |
|   //
 | |
|   //      This metaprogram checks if T is an optional
 | |
|   //
 | |
| 
 | |
|     template <class T>
 | |
|     struct is_optional
 | |
|       : mpl::false_
 | |
|     {};
 | |
| 
 | |
|     template <BOOST_PYTHON_OVERLOAD_TYPES>
 | |
|     struct is_optional<optional<BOOST_PYTHON_OVERLOAD_ARGS> >
 | |
|       : mpl::true_
 | |
|     {};
 | |
|   
 | |
| 
 | |
|   template <int NDefaults>
 | |
|   struct define_class_init_helper;
 | |
| 
 | |
| } // namespace detail
 | |
| 
 | |
| template <class DerivedT>
 | |
| struct init_base : def_visitor<DerivedT>
 | |
| {
 | |
|     init_base(char const* doc_, detail::keyword_range const& keywords_)
 | |
|         : m_doc(doc_), m_keywords(keywords_)
 | |
|     {}
 | |
|         
 | |
|     init_base(char const* doc_)
 | |
|         : m_doc(doc_)
 | |
|     {}
 | |
| 
 | |
|     DerivedT const& derived() const
 | |
|     {
 | |
|         return *static_cast<DerivedT const*>(this);
 | |
|     }
 | |
|     
 | |
|     char const* doc_string() const
 | |
|     {
 | |
|         return m_doc;
 | |
|     }
 | |
| 
 | |
|     detail::keyword_range const& keywords() const
 | |
|     {
 | |
|         return m_keywords;
 | |
|     }
 | |
| 
 | |
|     static default_call_policies call_policies()
 | |
|     {
 | |
|         return default_call_policies();
 | |
|     }
 | |
| 
 | |
|  private:
 | |
|     //  visit
 | |
|     //
 | |
|     //      Defines a set of n_defaults + 1 constructors for its
 | |
|     //      class_<...> argument. Each constructor after the first has
 | |
|     //      one less argument to its right. Example:
 | |
|     //
 | |
|     //          init<int, optional<char, long, double> >
 | |
|     //
 | |
|     //      Defines:
 | |
|     //
 | |
|     //          __init__(int, char, long, double)
 | |
|     //          __init__(int, char, long)
 | |
|     //          __init__(int, char)
 | |
|     //          __init__(int)
 | |
|     template <class classT>
 | |
|     void visit(classT& cl) const
 | |
|     {
 | |
|         typedef typename DerivedT::signature signature;
 | |
|         typedef typename DerivedT::n_arguments n_arguments;
 | |
|         typedef typename DerivedT::n_defaults n_defaults;
 | |
|     
 | |
|         detail::define_class_init_helper<n_defaults::value>::apply(
 | |
|             cl
 | |
|           , derived().call_policies()
 | |
|           , signature()
 | |
|           , n_arguments()
 | |
|           , derived().doc_string()
 | |
|           , derived().keywords());
 | |
|     }
 | |
|     
 | |
|     friend class python::def_visitor_access;
 | |
|     
 | |
|  private: // data members
 | |
|     char const* m_doc;
 | |
|     detail::keyword_range m_keywords;
 | |
| };
 | |
| 
 | |
| template <class CallPoliciesT, class InitT>
 | |
| class init_with_call_policies
 | |
|     : public init_base<init_with_call_policies<CallPoliciesT, InitT> >
 | |
| {
 | |
|     typedef init_base<init_with_call_policies<CallPoliciesT, InitT> > base;
 | |
|  public:
 | |
|     typedef typename InitT::n_arguments n_arguments;
 | |
|     typedef typename InitT::n_defaults n_defaults;
 | |
|     typedef typename InitT::signature signature;
 | |
| 
 | |
|     init_with_call_policies(
 | |
|         CallPoliciesT const& policies_
 | |
|         , char const* doc_
 | |
|         , detail::keyword_range const& keywords
 | |
|         )
 | |
|         : base(doc_, keywords)
 | |
|         , m_policies(policies_)
 | |
|     {}
 | |
| 
 | |
|     CallPoliciesT const& call_policies() const
 | |
|     {
 | |
|         return this->m_policies;
 | |
|     }
 | |
|     
 | |
|  private: // data members
 | |
|     CallPoliciesT m_policies;
 | |
| };
 | |
| 
 | |
| //
 | |
| // drop1<S> is the initial length(S) elements of S
 | |
| //
 | |
| namespace detail
 | |
| {
 | |
|   template <class S>
 | |
|   struct drop1
 | |
|     : mpl::iterator_range<
 | |
|           typename mpl::begin<S>::type
 | |
|         , typename mpl::prior<
 | |
|               typename mpl::end<S>::type
 | |
|           >::type
 | |
|       >
 | |
|   {};
 | |
| }
 | |
| 
 | |
| template <BOOST_PYTHON_OVERLOAD_TYPES>
 | |
| class init : public init_base<init<BOOST_PYTHON_OVERLOAD_ARGS> >
 | |
| {
 | |
|     typedef init_base<init<BOOST_PYTHON_OVERLOAD_ARGS> > base;
 | |
|  public:
 | |
|     typedef init<BOOST_PYTHON_OVERLOAD_ARGS> self_t;
 | |
| 
 | |
|     init(char const* doc_ = 0)
 | |
|         : base(doc_)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     template <std::size_t N>
 | |
|     init(char const* doc_, detail::keywords<N> const& kw)
 | |
|         : base(doc_, kw.range())
 | |
|     {
 | |
|         typedef typename detail::error::more_keywords_than_init_arguments<
 | |
|             N, n_arguments::value + 1
 | |
|             >::too_many_keywords assertion BOOST_ATTRIBUTE_UNUSED;
 | |
|     }
 | |
| 
 | |
|     template <std::size_t N>
 | |
|     init(detail::keywords<N> const& kw, char const* doc_ = 0)
 | |
|         : base(doc_, kw.range())
 | |
|     {
 | |
|         typedef typename detail::error::more_keywords_than_init_arguments<
 | |
|             N, n_arguments::value + 1
 | |
|             >::too_many_keywords assertion BOOST_ATTRIBUTE_UNUSED;
 | |
|     }
 | |
| 
 | |
|     template <class CallPoliciesT>
 | |
|     init_with_call_policies<CallPoliciesT, self_t>
 | |
|     operator[](CallPoliciesT const& policies) const
 | |
|     {
 | |
|         return init_with_call_policies<CallPoliciesT, self_t>(
 | |
|             policies, this->doc_string(), this->keywords());
 | |
|     }
 | |
| 
 | |
|     typedef detail::type_list<BOOST_PYTHON_OVERLOAD_ARGS> signature_;
 | |
| 
 | |
|     typedef detail::is_optional<
 | |
|         typename mpl::eval_if<
 | |
|             mpl::empty<signature_>
 | |
|           , mpl::false_
 | |
|           , mpl::back<signature_>
 | |
|         >::type
 | |
|     > back_is_optional;
 | |
|     
 | |
|     typedef typename mpl::eval_if<
 | |
|         back_is_optional
 | |
|       , mpl::back<signature_>
 | |
|       , mpl::vector0<>
 | |
|     >::type optional_args;
 | |
| 
 | |
|     typedef typename mpl::eval_if<
 | |
|         back_is_optional
 | |
|       , mpl::if_<
 | |
|             mpl::empty<optional_args>
 | |
|           , detail::drop1<signature_>
 | |
|           , mpl::joint_view<
 | |
|                 detail::drop1<signature_>
 | |
|               , optional_args
 | |
|             >
 | |
|         >
 | |
|       , signature_
 | |
|     >::type signature;
 | |
| 
 | |
|     // TODO: static assert to make sure there are no other optional elements
 | |
| 
 | |
|     // Count the number of default args
 | |
|     typedef mpl::size<optional_args> n_defaults;
 | |
|     typedef mpl::size<signature> n_arguments;
 | |
| };
 | |
| 
 | |
| ///////////////////////////////////////////////////////////////////////////////
 | |
| //
 | |
| //  optional
 | |
| //
 | |
| //      optional<T0...TN>::type returns a typelist.
 | |
| //
 | |
| ///////////////////////////////////////////////////////////////////////////////
 | |
| template <BOOST_PYTHON_OVERLOAD_TYPES>
 | |
| struct optional
 | |
|     : detail::type_list<BOOST_PYTHON_OVERLOAD_ARGS>
 | |
| {
 | |
| };
 | |
| 
 | |
| namespace detail
 | |
| {
 | |
|   template <class ClassT, class CallPoliciesT, class Signature, class NArgs>
 | |
|   inline void def_init_aux(
 | |
|       ClassT& cl
 | |
|       , Signature const&
 | |
|       , NArgs
 | |
|       , CallPoliciesT const& policies
 | |
|       , char const* doc
 | |
|       , detail::keyword_range const& keywords_
 | |
|       )
 | |
|   {
 | |
|       cl.def(
 | |
|           "__init__"
 | |
|         , detail::make_keyword_range_constructor<Signature,NArgs>(
 | |
|               policies
 | |
|             , keywords_
 | |
|             , (typename ClassT::metadata::holder*)0
 | |
|           )
 | |
|         , doc
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   ///////////////////////////////////////////////////////////////////////////////
 | |
|   //
 | |
|   //  define_class_init_helper<N>::apply
 | |
|   //
 | |
|   //      General case
 | |
|   //
 | |
|   //      Accepts a class_ and an arguments list. Defines a constructor
 | |
|   //      for the class given the arguments and recursively calls
 | |
|   //      define_class_init_helper<N-1>::apply with one fewer argument (the
 | |
|   //      rightmost argument is shaved off)
 | |
|   //
 | |
|   ///////////////////////////////////////////////////////////////////////////////
 | |
|   template <int NDefaults>
 | |
|   struct define_class_init_helper
 | |
|   {
 | |
| 
 | |
|       template <class ClassT, class CallPoliciesT, class Signature, class NArgs>
 | |
|       static void apply(
 | |
|           ClassT& cl
 | |
|           , CallPoliciesT const& policies
 | |
|           , Signature const& args
 | |
|           , NArgs
 | |
|           , char const* doc
 | |
|           , detail::keyword_range keywords)
 | |
|       {
 | |
|           detail::def_init_aux(cl, args, NArgs(), policies, doc, keywords);
 | |
| 
 | |
|           if (keywords.second > keywords.first)
 | |
|               --keywords.second;
 | |
| 
 | |
|           typedef typename mpl::prior<NArgs>::type next_nargs;
 | |
|           define_class_init_helper<NDefaults-1>::apply(
 | |
|               cl, policies, Signature(), next_nargs(), doc, keywords);
 | |
|       }
 | |
|   };
 | |
| 
 | |
|   ///////////////////////////////////////////////////////////////////////////////
 | |
|   //
 | |
|   //  define_class_init_helper<0>::apply
 | |
|   //
 | |
|   //      Terminal case
 | |
|   //
 | |
|   //      Accepts a class_ and an arguments list. Defines a constructor
 | |
|   //      for the class given the arguments.
 | |
|   //
 | |
|   ///////////////////////////////////////////////////////////////////////////////
 | |
|   template <>
 | |
|   struct define_class_init_helper<0> {
 | |
| 
 | |
|       template <class ClassT, class CallPoliciesT, class Signature, class NArgs>
 | |
|       static void apply(
 | |
|           ClassT& cl
 | |
|         , CallPoliciesT const& policies
 | |
|         , Signature const& args
 | |
|         , NArgs
 | |
|         , char const* doc
 | |
|         , detail::keyword_range const& keywords)
 | |
|       {
 | |
|           detail::def_init_aux(cl, args, NArgs(), policies, doc, keywords);
 | |
|       }
 | |
|   };
 | |
| }
 | |
| 
 | |
| }} // namespace boost::python
 | |
| 
 | |
| #undef BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT
 | |
| #undef BOOST_PYTHON_OVERLOAD_TYPES
 | |
| #undef BOOST_PYTHON_OVERLOAD_ARGS
 | |
| #undef BOOST_PYTHON_IS_OPTIONAL_VALUE
 | |
| #undef BOOST_PYTHON_APPEND_TO_INIT
 | |
| 
 | |
| ///////////////////////////////////////////////////////////////////////////////
 | |
| #endif // INIT_JDG20020820_HPP
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | 
