Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:41

0001 ///////////////////////////////////////////////////////////////////////////////
0002 //
0003 // Copyright David Abrahams 2002, Joel de Guzman, 2002.
0004 // Distributed under the Boost Software License, Version 1.0. (See
0005 // accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt)
0007 //
0008 ///////////////////////////////////////////////////////////////////////////////
0009 #ifndef INIT_JDG20020820_HPP
0010 #define INIT_JDG20020820_HPP
0011 
0012 # include <boost/python/detail/prefix.hpp>
0013 
0014 #include <boost/python/detail/type_list.hpp>
0015 #include <boost/python/args_fwd.hpp>
0016 #include <boost/python/detail/make_keyword_range_fn.hpp>
0017 #include <boost/python/def_visitor.hpp>
0018 
0019 #include <boost/mpl/if.hpp>
0020 #include <boost/mpl/eval_if.hpp>
0021 #include <boost/mpl/size.hpp>
0022 #include <boost/mpl/iterator_range.hpp>
0023 #include <boost/mpl/empty.hpp>
0024 #include <boost/mpl/begin_end.hpp>
0025 #include <boost/mpl/bool.hpp>
0026 #include <boost/mpl/prior.hpp>
0027 #include <boost/mpl/joint_view.hpp>
0028 #include <boost/mpl/back.hpp>
0029 
0030 #include <boost/python/detail/type_traits.hpp>
0031 
0032 #include <boost/preprocessor/enum_params_with_a_default.hpp>
0033 #include <boost/preprocessor/enum_params.hpp>
0034 
0035 #include <utility>
0036 
0037 ///////////////////////////////////////////////////////////////////////////////
0038 #define BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT                                \
0039     BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(                                        \
0040         BOOST_PYTHON_MAX_ARITY,                                                 \
0041         class T,                                                                \
0042         mpl::void_)                                                             \
0043 
0044 #define BOOST_PYTHON_OVERLOAD_TYPES                                             \
0045     BOOST_PP_ENUM_PARAMS_Z(1,                                                   \
0046         BOOST_PYTHON_MAX_ARITY,                                                 \
0047         class T)                                                                \
0048 
0049 #define BOOST_PYTHON_OVERLOAD_ARGS                                              \
0050     BOOST_PP_ENUM_PARAMS_Z(1,                                                   \
0051         BOOST_PYTHON_MAX_ARITY,                                                 \
0052         T)                                                                      \
0053 
0054 ///////////////////////////////////////////////////////////////////////////////
0055 namespace boost { namespace python {
0056 
0057 template <BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT>
0058 class init; // forward declaration
0059 
0060 
0061 template <BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT>
0062 struct optional; // forward declaration
0063 
0064 namespace detail
0065 {
0066   namespace error
0067   {
0068     template <int keywords, int init_args>
0069     struct more_keywords_than_init_arguments
0070     {
0071         typedef char too_many_keywords[init_args - keywords >= 0 ? 1 : -1] BOOST_ATTRIBUTE_UNUSED;
0072     };
0073   }
0074 
0075   //  is_optional<T>::value
0076   //
0077   //      This metaprogram checks if T is an optional
0078   //
0079 
0080     template <class T>
0081     struct is_optional
0082       : mpl::false_
0083     {};
0084 
0085     template <BOOST_PYTHON_OVERLOAD_TYPES>
0086     struct is_optional<optional<BOOST_PYTHON_OVERLOAD_ARGS> >
0087       : mpl::true_
0088     {};
0089   
0090 
0091   template <int NDefaults>
0092   struct define_class_init_helper;
0093 
0094 } // namespace detail
0095 
0096 template <class DerivedT>
0097 struct init_base : def_visitor<DerivedT>
0098 {
0099     init_base(char const* doc_, detail::keyword_range const& keywords_)
0100         : m_doc(doc_), m_keywords(keywords_)
0101     {}
0102         
0103     init_base(char const* doc_)
0104         : m_doc(doc_)
0105     {}
0106 
0107     DerivedT const& derived() const
0108     {
0109         return *static_cast<DerivedT const*>(this);
0110     }
0111     
0112     char const* doc_string() const
0113     {
0114         return m_doc;
0115     }
0116 
0117     detail::keyword_range const& keywords() const
0118     {
0119         return m_keywords;
0120     }
0121 
0122     static default_call_policies call_policies()
0123     {
0124         return default_call_policies();
0125     }
0126 
0127  private:
0128     //  visit
0129     //
0130     //      Defines a set of n_defaults + 1 constructors for its
0131     //      class_<...> argument. Each constructor after the first has
0132     //      one less argument to its right. Example:
0133     //
0134     //          init<int, optional<char, long, double> >
0135     //
0136     //      Defines:
0137     //
0138     //          __init__(int, char, long, double)
0139     //          __init__(int, char, long)
0140     //          __init__(int, char)
0141     //          __init__(int)
0142     template <class classT>
0143     void visit(classT& cl) const
0144     {
0145         typedef typename DerivedT::signature signature;
0146         typedef typename DerivedT::n_arguments n_arguments;
0147         typedef typename DerivedT::n_defaults n_defaults;
0148     
0149         detail::define_class_init_helper<n_defaults::value>::apply(
0150             cl
0151           , derived().call_policies()
0152           , signature()
0153           , n_arguments()
0154           , derived().doc_string()
0155           , derived().keywords());
0156     }
0157     
0158     friend class python::def_visitor_access;
0159     
0160  private: // data members
0161     char const* m_doc;
0162     detail::keyword_range m_keywords;
0163 };
0164 
0165 template <class CallPoliciesT, class InitT>
0166 class init_with_call_policies
0167     : public init_base<init_with_call_policies<CallPoliciesT, InitT> >
0168 {
0169     typedef init_base<init_with_call_policies<CallPoliciesT, InitT> > base;
0170  public:
0171     typedef typename InitT::n_arguments n_arguments;
0172     typedef typename InitT::n_defaults n_defaults;
0173     typedef typename InitT::signature signature;
0174 
0175     init_with_call_policies(
0176         CallPoliciesT const& policies_
0177         , char const* doc_
0178         , detail::keyword_range const& keywords
0179         )
0180         : base(doc_, keywords)
0181         , m_policies(policies_)
0182     {}
0183 
0184     CallPoliciesT const& call_policies() const
0185     {
0186         return this->m_policies;
0187     }
0188     
0189  private: // data members
0190     CallPoliciesT m_policies;
0191 };
0192 
0193 //
0194 // drop1<S> is the initial length(S) elements of S
0195 //
0196 namespace detail
0197 {
0198   template <class S>
0199   struct drop1
0200     : mpl::iterator_range<
0201           typename mpl::begin<S>::type
0202         , typename mpl::prior<
0203               typename mpl::end<S>::type
0204           >::type
0205       >
0206   {};
0207 }
0208 
0209 template <BOOST_PYTHON_OVERLOAD_TYPES>
0210 class init : public init_base<init<BOOST_PYTHON_OVERLOAD_ARGS> >
0211 {
0212     typedef init_base<init<BOOST_PYTHON_OVERLOAD_ARGS> > base;
0213  public:
0214     typedef init<BOOST_PYTHON_OVERLOAD_ARGS> self_t;
0215 
0216     init(char const* doc_ = 0)
0217         : base(doc_)
0218     {
0219     }
0220 
0221     template <std::size_t N>
0222     init(char const* doc_, detail::keywords<N> const& kw)
0223         : base(doc_, kw.range())
0224     {
0225         typedef typename detail::error::more_keywords_than_init_arguments<
0226             N, n_arguments::value + 1
0227             >::too_many_keywords assertion BOOST_ATTRIBUTE_UNUSED;
0228     }
0229 
0230     template <std::size_t N>
0231     init(detail::keywords<N> const& kw, char const* doc_ = 0)
0232         : base(doc_, kw.range())
0233     {
0234         typedef typename detail::error::more_keywords_than_init_arguments<
0235             N, n_arguments::value + 1
0236             >::too_many_keywords assertion BOOST_ATTRIBUTE_UNUSED;
0237     }
0238 
0239     template <class CallPoliciesT>
0240     init_with_call_policies<CallPoliciesT, self_t>
0241     operator[](CallPoliciesT const& policies) const
0242     {
0243         return init_with_call_policies<CallPoliciesT, self_t>(
0244             policies, this->doc_string(), this->keywords());
0245     }
0246 
0247     typedef detail::type_list<BOOST_PYTHON_OVERLOAD_ARGS> signature_;
0248 
0249     typedef detail::is_optional<
0250         typename mpl::eval_if<
0251             mpl::empty<signature_>
0252           , mpl::false_
0253           , mpl::back<signature_>
0254         >::type
0255     > back_is_optional;
0256     
0257     typedef typename mpl::eval_if<
0258         back_is_optional
0259       , mpl::back<signature_>
0260       , mpl::vector0<>
0261     >::type optional_args;
0262 
0263     typedef typename mpl::eval_if<
0264         back_is_optional
0265       , mpl::if_<
0266             mpl::empty<optional_args>
0267           , detail::drop1<signature_>
0268           , mpl::joint_view<
0269                 detail::drop1<signature_>
0270               , optional_args
0271             >
0272         >
0273       , signature_
0274     >::type signature;
0275 
0276     // TODO: static assert to make sure there are no other optional elements
0277 
0278     // Count the number of default args
0279     typedef mpl::size<optional_args> n_defaults;
0280     typedef mpl::size<signature> n_arguments;
0281 };
0282 
0283 ///////////////////////////////////////////////////////////////////////////////
0284 //
0285 //  optional
0286 //
0287 //      optional<T0...TN>::type returns a typelist.
0288 //
0289 ///////////////////////////////////////////////////////////////////////////////
0290 template <BOOST_PYTHON_OVERLOAD_TYPES>
0291 struct optional
0292     : detail::type_list<BOOST_PYTHON_OVERLOAD_ARGS>
0293 {
0294 };
0295 
0296 namespace detail
0297 {
0298   template <class ClassT, class CallPoliciesT, class Signature, class NArgs>
0299   inline void def_init_aux(
0300       ClassT& cl
0301       , Signature const&
0302       , NArgs
0303       , CallPoliciesT const& policies
0304       , char const* doc
0305       , detail::keyword_range const& keywords_
0306       )
0307   {
0308       cl.def(
0309           "__init__"
0310         , detail::make_keyword_range_constructor<Signature,NArgs>(
0311               policies
0312             , keywords_
0313             , (typename ClassT::metadata::holder*)0
0314           )
0315         , doc
0316       );
0317   }
0318 
0319   ///////////////////////////////////////////////////////////////////////////////
0320   //
0321   //  define_class_init_helper<N>::apply
0322   //
0323   //      General case
0324   //
0325   //      Accepts a class_ and an arguments list. Defines a constructor
0326   //      for the class given the arguments and recursively calls
0327   //      define_class_init_helper<N-1>::apply with one fewer argument (the
0328   //      rightmost argument is shaved off)
0329   //
0330   ///////////////////////////////////////////////////////////////////////////////
0331   template <int NDefaults>
0332   struct define_class_init_helper
0333   {
0334 
0335       template <class ClassT, class CallPoliciesT, class Signature, class NArgs>
0336       static void apply(
0337           ClassT& cl
0338           , CallPoliciesT const& policies
0339           , Signature const& args
0340           , NArgs
0341           , char const* doc
0342           , detail::keyword_range keywords)
0343       {
0344           detail::def_init_aux(cl, args, NArgs(), policies, doc, keywords);
0345 
0346           if (keywords.second > keywords.first)
0347               --keywords.second;
0348 
0349           typedef typename mpl::prior<NArgs>::type next_nargs;
0350           define_class_init_helper<NDefaults-1>::apply(
0351               cl, policies, Signature(), next_nargs(), doc, keywords);
0352       }
0353   };
0354 
0355   ///////////////////////////////////////////////////////////////////////////////
0356   //
0357   //  define_class_init_helper<0>::apply
0358   //
0359   //      Terminal case
0360   //
0361   //      Accepts a class_ and an arguments list. Defines a constructor
0362   //      for the class given the arguments.
0363   //
0364   ///////////////////////////////////////////////////////////////////////////////
0365   template <>
0366   struct define_class_init_helper<0> {
0367 
0368       template <class ClassT, class CallPoliciesT, class Signature, class NArgs>
0369       static void apply(
0370           ClassT& cl
0371         , CallPoliciesT const& policies
0372         , Signature const& args
0373         , NArgs
0374         , char const* doc
0375         , detail::keyword_range const& keywords)
0376       {
0377           detail::def_init_aux(cl, args, NArgs(), policies, doc, keywords);
0378       }
0379   };
0380 }
0381 
0382 }} // namespace boost::python
0383 
0384 #undef BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT
0385 #undef BOOST_PYTHON_OVERLOAD_TYPES
0386 #undef BOOST_PYTHON_OVERLOAD_ARGS
0387 #undef BOOST_PYTHON_IS_OPTIONAL_VALUE
0388 #undef BOOST_PYTHON_APPEND_TO_INIT
0389 
0390 ///////////////////////////////////////////////////////////////////////////////
0391 #endif // INIT_JDG20020820_HPP
0392 
0393 
0394 
0395 
0396 
0397 
0398 
0399