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