diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp index 09612c16..53c5d2f3 100644 --- a/include/boost/python/class.hpp +++ b/include/boost/python/class.hpp @@ -38,7 +38,6 @@ # include # include -# include # include # include # include @@ -59,11 +58,9 @@ namespace boost { namespace python { -enum no_init_t { no_init }; +template struct def_visitor; -struct def_arg_base {}; -template -struct def_arg : def_arg_base {}; // Generic visitor +enum no_init_t { no_init }; namespace detail { @@ -90,9 +87,6 @@ namespace detail template struct has_noncopyable; - template - struct operator_; - // Register to_python converters for a class T. The first argument // will be mpl::true_ unless noncopyable was specified as a // class_<...> template parameter. The 2nd argument is a pointer to @@ -249,7 +243,7 @@ class class_ : public objects::class_base : base(name, id_vector::size, id_vector().ids) { this->register_(); - define_init(*this, i.derived()); + this->def(i); this->set_instance_size(holder_selector::additional_size()); } @@ -259,26 +253,18 @@ class class_ : public objects::class_base : base(name, id_vector::size, id_vector().ids, doc) { this->register_(); - define_init(*this, i.derived()); + this->def(i); this->set_instance_size(holder_selector::additional_size()); } public: // member functions - // Define additional constructors - template - self& def(init_base const& i) - { - define_init(*this, i.derived()); - return *this; - } - // Generic visitation template - self& def(def_arg const& visitor) + self& def(def_visitor const& visitor) { - static_cast(visitor).visit(*this); - return *this; + visitor.visit(*this); + return *this; } // Wrap a member function or a non-member function which can take @@ -324,13 +310,6 @@ class class_ : public objects::class_base return *this; } - template - self& def(detail::operator_ const& op) - { - typedef detail::operator_ op_t; - return this->def(op.name(), &op_t::template apply::execute); - } - // // Data member access // @@ -476,42 +455,27 @@ class class_ : public objects::class_base inline void register_() const; // - // These three overloads discriminate between def() as applied to - // things which are already wrapped into callable python::object - // instances, a generic visitor, and everything else. + // These two overloads discriminate between def() as applied to a + // generic visitor and everything else. // - template + template inline void def_impl( char const* name - , F f - , detail::def_helper const& helper - , object const*) + , LeafVisitor + , Helper const& helper + , def_visitor const* v + ) { - // It's too late to specify anything other than docstrings, if - // the callable object is already wrapped. - BOOST_STATIC_ASSERT( - (is_same::value - || detail::is_string_literal::value)); - - objects::add_to_namespace(*this, name, f, helper.doc()); + v->visit(*this, name, helper); } - template - inline void def_impl( - char const* name - , def_arg const& visitor - , detail::def_helper const& helper - , def_arg_base const*) - { - static_cast(visitor).visit(*this, name); - } - template inline void def_impl( char const* name - , Fn fn - , Helper const& helper - , ...) + , Fn fn + , Helper const& helper + , ... + ) { objects::add_to_namespace( *this, name, @@ -578,9 +542,11 @@ class class_ : public objects::class_base , ...) { this->def_impl( - name, fn - , detail::def_helper(a1) - , &fn); + name + , fn + , detail::def_helper(a1) + , &fn + ); } }; diff --git a/include/boost/python/def_visitor.hpp b/include/boost/python/def_visitor.hpp new file mode 100755 index 00000000..50c510f4 --- /dev/null +++ b/include/boost/python/def_visitor.hpp @@ -0,0 +1,87 @@ +// Copyright David Abrahams 2003. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef DEF_VISITOR_DWA2003810_HPP +# define DEF_VISITOR_DWA2003810_HPP + +# include +# include + +namespace boost { namespace python { + +template class def_visitor; +template class class_; + +class def_visitor_access +{ +# if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) \ + || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) + // Tasteless as this may seem, making all members public allows member templates + // to work in the absence of member template friends. + public: +# else + template friend class def_visitor; +# endif + + // unnamed visit, c.f. init<...>, container suites + template + static void visit(V const& v, classT& c) + { + v.derived_visitor().visit(c); + } + + // named visit, c.f. object, pure_virtual + template + static void visit( + V const& v + , classT& c + , char const* name + , OptionalArgs const& options + ) + { + v.derived_visitor().visit(c, name, options); + } + +}; + + +template +class def_visitor +{ + friend class def_visitor_access; + +# if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) \ + || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) + // Tasteless as this may seem, making all members public allows member templates + // to work in the absence of member template friends. + public: +# else + template friend class class_; +# endif + + // unnamed visit, c.f. init<...>, container suites + template + void visit(classT& c) const + { + def_visitor_access::visit(*this, c); + } + + // named visit, c.f. object, pure_virtual + template + void visit(classT& c, char const* name, OptionalArgs const& options) const + { + def_visitor_access::visit(*this, c, name, options); + } + + protected: + DerivedVisitor const& derived_visitor() const + { + return static_cast(*this); + } +}; + +}} // namespace boost::python + +#endif // DEF_VISITOR_DWA2003810_HPP diff --git a/include/boost/python/detail/def_helper.hpp b/include/boost/python/detail/def_helper.hpp index 98933bd4..12ed5099 100644 --- a/include/boost/python/detail/def_helper.hpp +++ b/include/boost/python/detail/def_helper.hpp @@ -18,6 +18,7 @@ # include # include # include +# include namespace boost { namespace python { @@ -143,7 +144,7 @@ namespace detail // are expected to be the types of the actual (optional) arguments // passed to def(). // - template + template struct def_helper { // A tuple type which begins with references to the supplied diff --git a/include/boost/python/detail/def_helper_fwd.hpp b/include/boost/python/detail/def_helper_fwd.hpp new file mode 100755 index 00000000..38af07f3 --- /dev/null +++ b/include/boost/python/detail/def_helper_fwd.hpp @@ -0,0 +1,18 @@ +// Copyright David Abrahams 2003. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef DEF_HELPER_FWD_DWA2003810_HPP +# define DEF_HELPER_FWD_DWA2003810_HPP + +# include + +namespace boost { namespace python { namespace detail { + +template +struct def_helper; + +}}} // namespace boost::python::detail + +#endif // DEF_HELPER_FWD_DWA2003810_HPP diff --git a/include/boost/python/indexing/indexing_suite.hpp b/include/boost/python/indexing/indexing_suite.hpp index 6ec7240e..01645501 100644 --- a/include/boost/python/indexing/indexing_suite.hpp +++ b/include/boost/python/indexing/indexing_suite.hpp @@ -7,7 +7,7 @@ #ifndef INDEXING_SUITE_JDG20036_HPP # define INDEXING_SUITE_JDG20036_HPP -# include +# include # include # include # include @@ -105,7 +105,7 @@ namespace boost { namespace python { , class Index = typename Container::size_type > class indexing_suite - : public def_arg< + : public def_visitor< indexing_suite< Container , DerivedPolicies @@ -162,7 +162,7 @@ namespace boost { namespace python { , Index> >::type slice_handler; - public: + private: // def visitation template void visit(Class& cl) const @@ -183,7 +183,9 @@ namespace boost { namespace python { ; } - private: + friend class python::def_visitor_access; + + private: static object base_get_item(back_reference container, PyObject* i) diff --git a/include/boost/python/init.hpp b/include/boost/python/init.hpp index aea9d635..0a052166 100644 --- a/include/boost/python/init.hpp +++ b/include/boost/python/init.hpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -110,10 +111,13 @@ namespace detail #endif + template + struct define_class_init_helper; + } // namespace detail template -struct init_base +struct init_base : def_visitor { init_base(char const* doc_, detail::keyword_range const& keywords_) : m_doc(doc_), m_keywords(keywords_) @@ -122,7 +126,7 @@ struct init_base init_base(char const* doc_) : m_doc(doc_) {} - + DerivedT const& derived() const { return *static_cast(this); @@ -142,6 +146,39 @@ struct init_base { 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; @@ -326,7 +363,8 @@ namespace detail // /////////////////////////////////////////////////////////////////////////////// template - struct define_class_init_helper { + struct define_class_init_helper + { template static void apply( @@ -375,39 +413,6 @@ namespace detail }; } -/////////////////////////////////////////////////////////////////////////////// -// -// define_init -// -// Accepts a class_ and an init-list. Defines a set of constructors for -// the class given the arguments. The init list (see init above) has -// n_defaults (number of default arguments and n_arguments (number of -// actual arguments). This function defines n_defaults + 1 constructors -// for the class. 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 -define_init(ClassT& cl, InitT const& i) -{ - typedef typename InitT::signature signature; - typedef typename InitT::n_arguments n_arguments; - typedef typename InitT::n_defaults n_defaults; - - detail::define_class_init_helper::apply( - cl, i.call_policies(), signature(), n_arguments(), i.doc_string(), i.keywords()); -} - }} // namespace boost::python #undef BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT diff --git a/include/boost/python/object_core.hpp b/include/boost/python/object_core.hpp index 7208e003..f9056055 100755 --- a/include/boost/python/object_core.hpp +++ b/include/boost/python/object_core.hpp @@ -17,16 +17,22 @@ # include # include # include +# include # include # include # include +# include # include # include # include +# include +# include +# include + namespace boost { namespace python { namespace converter @@ -69,7 +75,7 @@ namespace api typedef PyObject* (object::*bool_type)() const; template - class object_operators + class object_operators : public def_visitor { protected: # if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 @@ -157,7 +163,23 @@ namespace api slice_bound::type(start) , slice_bound::type(end)); } -# endif +# endif + + private: // def visitation for adding callable objects as class methods + template + void visit(ClassT& cl, char const* name, python::detail::def_helper const& helper) const + { + // It's too late to specify anything other than docstrings if + // the callable object is already wrapped. + BOOST_STATIC_ASSERT( + (is_same::value + || detail::is_string_literal::value)); + + objects::add_to_namespace(cl, name, this->derived_visitor(), helper.doc()); + } + + friend class python::def_visitor_access; + private: // there is a confirmed CWPro8 codegen bug here. We prevent the // early destruction of a temporary by binding a named object diff --git a/include/boost/python/operators.hpp b/include/boost/python/operators.hpp index e72c55a4..f64ec22a 100644 --- a/include/boost/python/operators.hpp +++ b/include/boost/python/operators.hpp @@ -8,11 +8,13 @@ # include +# include # include # include # include # include # include +# include # include # include # include @@ -121,20 +123,41 @@ namespace detail // self_t template struct operator_ - : mpl::if_< - is_same - , typename mpl::if_< - is_same - , binary_op - , binary_op_l::type> - >::type - , typename mpl::if_< - is_same - , unary_op - , binary_op_r::type> - >::type - >::type + : def_visitor > { + private: + template + void visit(ClassT& cl) const + { + typedef typename mpl::apply_if< + is_same + , mpl::if_< + is_same + , binary_op + , binary_op_l< + id + , BOOST_DEDUCED_TYPENAME unwrap_other::type + > + > + , mpl::if_< + is_same + , unary_op + , binary_op_r< + id + , BOOST_DEDUCED_TYPENAME unwrap_other::type + > + > + >::type generator; + + cl.def( + generator::name() + , &generator::template apply< + BOOST_DEDUCED_TYPENAME ClassT::wrapped_type + >::execute + ); + } + + friend class python::def_visitor_access; }; } diff --git a/src/list.cpp b/src/list.cpp index aab01bc3..30ee78a0 100644 --- a/src/list.cpp +++ b/src/list.cpp @@ -7,6 +7,7 @@ namespace boost { namespace python { namespace detail { + detail::new_non_null_reference list_base::call(object const& arg_) { return (detail::new_non_null_reference) @@ -37,14 +38,7 @@ void list_base::append(object_cref x) } } -long list_base::count(object_cref value) const -{ - object result_obj(this->attr("count")(value)); - long result = PyInt_AsLong(result_obj.ptr()); - if (result == -1) - throw_error_already_set(); - return result; -} +//long list_base::count(object_cref value) const; void list_base::extend(object_cref sequence) { @@ -132,4 +126,15 @@ void list_base::sort(object_cref cmpfunc) this->attr("sort")(cmpfunc); } +// For some reason, moving this to the end of the TU suppresses an ICE +// with vc6. +long list_base::count(object_cref value) const +{ + object result_obj(this->attr("count")(value)); + long result = PyInt_AsLong(result_obj.ptr()); + if (result == -1) + throw_error_already_set(); + return result; +} + }}} // namespace boost::python diff --git a/src/object/class.cpp b/src/object/class.cpp index d8c5e356..2a95448a 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -3,6 +3,9 @@ // copyright notice appears in all copies. This software is provided // "as is" without express or implied warranty, and with no claim as // to its suitability for any purpose. + +#include // #including this first is an intel6 workaround + #include #include #include diff --git a/src/str.cpp b/src/str.cpp index a8a2383f..fc29aa03 100644 --- a/src/str.cpp +++ b/src/str.cpp @@ -22,14 +22,6 @@ str_base::str_base(object_cref other) : object(str_base::call(other)) {} -namespace -{ - new_reference new_attr_reference(object const* obj, char const* name) - { - return new_reference(incref(object(obj->attr(name)).ptr())); - } -} - #define BOOST_PYTHON_FORMAT_OBJECT(z, n, data) "O" #define BOOST_PYTHON_OBJECT_PTR(z, n, data) , x##n .ptr() @@ -320,5 +312,5 @@ BOOST_PYTHON_DEFINE_STR_METHOD(title, 0) BOOST_PYTHON_DEFINE_STR_METHOD(translate, 1) BOOST_PYTHON_DEFINE_STR_METHOD(translate, 2) BOOST_PYTHON_DEFINE_STR_METHOD(upper, 0) - + }}} // namespace boost::python