/////////////////////////////////////////////////////////////////////////////// // // 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /////////////////////////////////////////////////////////////////////////////// #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 class init; // forward declaration template struct optional; // forward declaration namespace detail { namespace error { template struct more_keywords_than_init_arguments { typedef char too_many_keywords[init_args - keywords >= 0 ? 1 : -1] BOOST_ATTRIBUTE_UNUSED; }; } // is_optional::value // // This metaprogram checks if T is an optional // template struct is_optional : mpl::false_ {}; template struct is_optional > : mpl::true_ {}; template struct define_class_init_helper; } // namespace detail template struct init_base : def_visitor { 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(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 > // // Defines: // // __init__(int, char, long, double) // __init__(int, char, long) // __init__(int, char) // __init__(int) template 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::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 init_with_call_policies : public init_base > { typedef init_base > 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 is the initial length(S) elements of S // namespace detail { template struct drop1 : mpl::iterator_range< typename mpl::begin::type , typename mpl::prior< typename mpl::end::type >::type > {}; } template class init : public init_base > { typedef init_base > base; public: typedef init self_t; init(char const* doc_ = 0) : base(doc_) { } template init(char const* doc_, detail::keywords 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 init(detail::keywords 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 init_with_call_policies operator[](CallPoliciesT const& policies) const { return init_with_call_policies( policies, this->doc_string(), this->keywords()); } typedef detail::type_list signature_; typedef detail::is_optional< typename mpl::eval_if< mpl::empty , mpl::false_ , mpl::back >::type > back_is_optional; typedef typename mpl::eval_if< back_is_optional , mpl::back , mpl::vector0<> >::type optional_args; typedef typename mpl::eval_if< back_is_optional , mpl::if_< mpl::empty , detail::drop1 , mpl::joint_view< detail::drop1 , 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 n_defaults; typedef mpl::size n_arguments; }; /////////////////////////////////////////////////////////////////////////////// // // optional // // optional::type returns a typelist. // /////////////////////////////////////////////////////////////////////////////// template struct optional : detail::type_list { }; namespace detail { template 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( policies , keywords_ , (typename ClassT::metadata::holder*)0 ) , doc ); } /////////////////////////////////////////////////////////////////////////////// // // define_class_init_helper::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::apply with one fewer argument (the // rightmost argument is shaved off) // /////////////////////////////////////////////////////////////////////////////// template struct define_class_init_helper { template 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::type next_nargs; define_class_init_helper::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 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