123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399 |
- ///////////////////////////////////////////////////////////////////////////////
- //
- // 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/python/detail/type_traits.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
|