From 615adc5fe6ee3a0563287d2fefb696ec226d6971 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 20 Jul 2004 03:16:49 +0000 Subject: [PATCH] Make slice work on vc6 Revamp/simplify class registration [SVN r23823] --- include/boost/python/class.hpp | 168 ++---------- .../converter/shared_ptr_from_python.hpp | 4 + include/boost/python/init.hpp | 18 +- include/boost/python/object/class.hpp | 2 - .../boost/python/object/class_converters.hpp | 93 ------- .../boost/python/object/class_metadata.hpp | 249 ++++++++++++++++++ include/boost/python/object/select_holder.hpp | 195 -------------- include/boost/python/object_core.hpp | 11 +- include/boost/python/pure_virtual.hpp | 4 +- include/boost/python/slice.hpp | 79 +++--- src/slice.cpp | 21 +- test/Jamfile | 6 +- test/injected.cpp | 2 +- test/int_map_indexing_suite.cpp | 16 ++ test/map_indexing_suite.cpp | 5 + test/operators.cpp | 1 + test/select_holder.cpp | 12 +- test/slice.cpp | 3 +- 18 files changed, 391 insertions(+), 498 deletions(-) delete mode 100644 include/boost/python/object/class_converters.hpp create mode 100755 include/boost/python/object/class_metadata.hpp delete mode 100644 include/boost/python/object/select_holder.hpp create mode 100755 test/int_map_indexing_suite.cpp diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp index 659f7fa7..d5c0de6a 100644 --- a/include/boost/python/class.hpp +++ b/include/boost/python/class.hpp @@ -8,10 +8,11 @@ # include +# include + # include # include -# include # include # include # include @@ -20,12 +21,9 @@ # include # include -# include -# include -# include +# include # include # include -# include # include # include @@ -33,7 +31,6 @@ # include # include -# include # include # include @@ -41,10 +38,7 @@ # include # include # include -# include -# include -# include # include # if BOOST_WORKAROUND(__MWERKS__, <= 0x3004) \ @@ -87,52 +81,6 @@ namespace detail type_info** p; }; - template - struct select_held_type; - - template - struct has_noncopyable; - - // 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 - // the type of holder that must be created. The 3rd argument is a - // reference to the Python type object to be created. - template - inline void register_class_to_python(mpl::true_, SelectHolder, T* = 0) - { - typedef typename SelectHolder::type holder; - force_instantiate(objects::class_cref_wrapper >()); - SelectHolder::register_(); - } - - template - inline void register_class_to_python(mpl::false_, SelectHolder, T* = 0) - { - SelectHolder::register_(); - } - - // - // register_wrapper_class -- register the relationship between a - // virtual function callback wrapper class and the class being - // wrapped. - // - template - inline void register_wrapper_class_impl(T*, T*, int) {} - - template - inline void register_wrapper_class_impl(Wrapper*, T*, ...) - { - objects::register_class_from_python >(); - objects::copy_class_object(type_id(), type_id()); - } - - template - inline void register_wrapper_class(Held* = 0, T* = 0) - { - register_wrapper_class_impl((Held*)0, (T*)0, 0); - } - template struct is_data_member_pointer : mpl::and_< @@ -212,34 +160,18 @@ class class_ : public objects::class_base { public: // types typedef objects::class_base base; + typedef class_ self; + typedef typename objects::class_metadata metadata; typedef T wrapped_type; - typedef class_ self; - BOOST_STATIC_CONSTANT(bool, is_copyable = (!detail::has_noncopyable::value)); - - // held_type - either T, a class derived from T or a smart pointer - // to a (class derived from) T. - typedef typename detail::select_held_type< - X1, typename detail::select_held_type< - X2, typename detail::select_held_type< - X3 - >::type>::type>::type held_type; - - typedef objects::select_holder select_holder; - private: // types - typedef typename detail::select_bases::type - >::type - >::type bases; - - // A helper class which will contain an array of id objects to be // passed to the base class constructor struct id_vector { + typedef typename metadata::bases bases; + id_vector() { // Stick the derived class id into the first element of the array @@ -272,8 +204,7 @@ class class_ : public objects::class_base inline class_(char const* name, init_base const& i) : base(name, id_vector::size, id_vector().ids) { - this->register_holder(); - this->def(i); + this->initialize(i); } // Construct with class name, docstring and init<> function @@ -281,8 +212,7 @@ class class_ : public objects::class_base inline class_(char const* name, char const* doc, init_base const& i) : base(name, id_vector::size, id_vector().ids, doc) { - this->register_holder(); - this->def(i); + this->initialize(i); } public: // member functions @@ -510,8 +440,22 @@ class class_ : public objects::class_base return this->add_static_property(name, python::make_getter(d), python::make_setter(d)); } - inline void register_() const; - inline void register_holder(); + template + inline void initialize(DefVisitor const& i) + { + metadata::register_(); // set up runtime metadata/conversions + + typedef typename metadata::holder holder; + this->set_instance_size( objects::additional_instance_size::value ); + + this->def(i); + } + + inline void initialize(no_init_t) + { + metadata::register_(); // set up runtime metadata/conversions + this->def_no_init(); + } // // These two overloads discriminate between def() as applied to a @@ -625,80 +569,26 @@ class class_ : public objects::class_base // implementations // -// register converters -template -inline void class_::register_() const -{ - objects::register_class_from_python(); - - typedef BOOST_DEDUCED_TYPENAME select_holder::held_type held_t; - detail::register_wrapper_class(); - - detail::register_class_to_python( - mpl::bool_() - , select_holder() - ); -} - -template -inline void class_::register_holder() -{ - this->register_(); - typedef typename select_holder::type holder; - this->set_instance_size( - objects::additional_instance_size::value - ); -} - template inline class_::class_(char const* name, char const* doc) : base(name, id_vector::size, id_vector().ids, doc) { - this->register_holder(); - select_holder::assert_default_constructible(); - this->def(init<>()); + this->initialize(init<>()); +// select_holder::assert_default_constructible(); } template inline class_::class_(char const* name, no_init_t) : base(name, id_vector::size, id_vector().ids) { - this->register_(); - this->def_no_init(); + this->initialize(no_init); } template inline class_::class_(char const* name, char const* doc, no_init_t) : base(name, id_vector::size, id_vector().ids, doc) { - this->register_(); - this->def_no_init(); -} - -namespace detail -{ - template - struct has_noncopyable - : mpl::or_< - is_same - , is_same - , is_same - > - {}; - - - template - struct select_held_type - : mpl::if_< - mpl::or_< - specifies_bases - , is_same - > - , Prev - , T - > - { - }; + this->initialize(no_init); } }} // namespace boost::python diff --git a/include/boost/python/converter/shared_ptr_from_python.hpp b/include/boost/python/converter/shared_ptr_from_python.hpp index acca976d..8e63ad0b 100644 --- a/include/boost/python/converter/shared_ptr_from_python.hpp +++ b/include/boost/python/converter/shared_ptr_from_python.hpp @@ -8,6 +8,10 @@ # include # include +# include +# include +# include +# include namespace boost { namespace python { namespace converter { diff --git a/include/boost/python/init.hpp b/include/boost/python/init.hpp index 04d8a667..9894d53e 100644 --- a/include/boost/python/init.hpp +++ b/include/boost/python/init.hpp @@ -328,17 +328,15 @@ namespace detail , detail::keyword_range const& keywords_ ) { - typedef typename ClassT::select_holder selector_t; - cl.def( - "__init__", - detail::make_keyword_range_constructor( - policies - , keywords_ - , selector_t::get() - ) - , doc - ); + "__init__" + , detail::make_keyword_range_constructor( + policies + , keywords_ + , (typename ClassT::metadata::holder*)0 + ) + , doc + ); } /////////////////////////////////////////////////////////////////////////////// diff --git a/include/boost/python/object/class.hpp b/include/boost/python/object/class.hpp index 22692011..10f66ed6 100644 --- a/include/boost/python/object/class.hpp +++ b/include/boost/python/object/class.hpp @@ -58,8 +58,6 @@ struct BOOST_PYTHON_DECL class_base : python::api::object void make_method_static(const char *method_name); }; -BOOST_PYTHON_DECL void copy_class_object(type_info const& src, type_info const& dst); - }}} // namespace boost::python::objects #endif // CLASS_DWA20011214_HPP diff --git a/include/boost/python/object/class_converters.hpp b/include/boost/python/object/class_converters.hpp deleted file mode 100644 index a891c994..00000000 --- a/include/boost/python/object/class_converters.hpp +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright David Abrahams 2002. 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 CLASS_CONVERTERS_DWA2002119_HPP -# define CLASS_CONVERTERS_DWA2002119_HPP - -# include -# include - -# include - -# include - -# include -# include - -# include - -# include - -namespace boost { namespace python { namespace objects { - -////////////////////////////////////////////////////////////////////// -// -// register_base_of - -// A BinaryMetaFunction object which registers a single base -// class of T, and the corresponding cast(s) -// - - -// register_downcast/do_nothing - -// Helpers for register_base_of<> which take care of registering -// down-casts -template -struct register_downcast -{ - static void execute() - { - register_conversion(true); - } -}; - -struct do_nothing -{ - static void execute() { } -}; - -// Here's where the real work gets done: -template -struct register_base_of -{ - // Here's the runtime part: - template - void operator()(Base*) const - { - // Register the Base class - register_dynamic_id(); - // Register the up-cast - register_conversion(false); - - // Register the down-cast, if appropriate. - mpl::if_< -# if BOOST_WORKAROUND(__MWERKS__, <= 0x2407) - mpl::true_ -# else - is_polymorphic -# endif - , register_downcast - , do_nothing - >::type::execute(); - } -}; - -// Brings into existence all converters associated with a class. Bases -// is expected to be an mpl sequence of base types. -template -inline void register_class_from_python(Derived* = 0, Bases* = 0) -{ - // Static object constructor performs registration - static converter::shared_ptr_from_python shared_ptr_registration; - - // register all up/downcasts here - register_dynamic_id(); - - // register each base in the sequence - mpl::for_each(register_base_of(), (Bases*)0, (add_pointer*)0); -} - -}}} // namespace boost::python::object - -#endif // CLASS_CONVERTERS_DWA2002119_HPP diff --git a/include/boost/python/object/class_metadata.hpp b/include/boost/python/object/class_metadata.hpp new file mode 100755 index 00000000..d9bda9b3 --- /dev/null +++ b/include/boost/python/object/class_metadata.hpp @@ -0,0 +1,249 @@ +// Copyright David Abrahams 2004. 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 CLASS_METADATA_DWA2004719_HPP +# define CLASS_METADATA_DWA2004719_HPP +# include + +# include +# include +# include +# include +# include +# include + +# include +# include + +# include +# include + +# include +# include +# include + +# include +# include +# include +# include +# include +# include +# include +# include +# include + +# include +# include + +namespace boost { namespace python { namespace objects { + +BOOST_PYTHON_DECL +void copy_class_object(type_info const& src, type_info const& dst); + +// +// Support for registering base/derived relationships +// +template +struct register_base_of +{ + template + inline void operator()(Base*) const + { + // Register the Base class + register_dynamic_id(); + + // Register the up-cast + register_conversion(false); + + // Register the down-cast, if appropriate. + this->register_downcast((Base*)0, is_polymorphic()); + } + + private: + static inline void register_downcast(void*, mpl::false_) {} + + template + static inline void register_downcast(Base*, mpl::true_) + { + register_conversion(true); + } + +}; + +// +// Preamble of register_class. Also used for callback classes, which +// need some registration of their own. +// +template +void register_shared_ptr_from_python_and_casts(T*, Bases) +{ + // Constructor performs registration + python::detail::force_instantiate(converter::shared_ptr_from_python()); + + // + // register all up/downcasts here. We're using the alternate + // interface to mpl::for_each to avoid an MSVC 6 bug. + // + register_dynamic_id(); + mpl::for_each(register_base_of(), (Bases*)0, (add_pointer*)0); +} + +// +// Helper for choosing the unnamed held_type argument +// +template +struct select_held_type + : mpl::if_< + mpl::or_< + python::detail::specifies_bases + , is_same + > + , Prev + , T + > +{ +}; + +template < + class T // class being wrapped + , class X1 // = detail::not_specified + , class X2 // = detail::not_specified + , class X3 // = detail::not_specified +> +struct class_metadata +{ + // + // Calculate the unnamed template arguments + // + + // held_type_arg -- not_specified, [a class derived from] T or a + // smart pointer to [a class derived from] T. Preserving + // not_specified allows us to give class_ a back-reference. + typedef typename select_held_type< + X1 + , typename select_held_type< + X2 + , typename select_held_type< + X3 + , python::detail::not_specified + >::type + >::type + >::type held_type_arg; + + // bases + typedef typename python::detail::select_bases< + X1 + , typename python::detail::select_bases< + X2 + , typename python::detail::select_bases< + X3 + , python::bases<> + >::type + >::type + >::type bases; + + typedef mpl::or_< + is_same + , is_same + , is_same + > is_noncopyable; + + // + // Holder computation. + // + + // Compute the actual type that will be held in the Holder. + typedef typename mpl::if_< + is_same, T, held_type_arg + >::type held_type; + + // Determine if the object will be held by value + typedef is_convertible use_value_holder; + + // Compute the "wrapped type", that is, if held_type is a smart + // pointer, we're talking about the pointee. + typedef typename mpl::apply_if< + use_value_holder + , mpl::identity + , pointee + >::type wrapper; + + // Determine whether wrapper needs to be separately registered + typedef is_base_and_derived use_callback_class; + + // Determine whether to use a holder with a back-reference + typedef mpl::or_< + use_callback_class + , has_back_reference + , is_same + > use_back_reference; + + // Select the holder. + typedef typename mpl::apply_if< + use_back_reference + , mpl::if_< + use_value_holder + , value_holder_back_reference + , pointer_holder_back_reference + > + , mpl::if_< + use_value_holder + , value_holder + , pointer_holder + > + >::type holder; + + inline static void register_() // Register the runtime metadata. + { + objects::register_shared_ptr_from_python_and_casts((T*)0, bases()); + + class_metadata::maybe_register_callback_class(use_callback_class()); + + class_metadata::maybe_register_class_to_python(is_noncopyable()); + + class_metadata::maybe_register_pointer_to_python( + (use_value_holder*)0, (use_back_reference*)0); + } + + private: + // + // Support for converting smart pointers to python + // + inline static void maybe_register_pointer_to_python(void*,void*) {} + + inline static void maybe_register_pointer_to_python(mpl::false_*, mpl::false_*) + { + python::detail::force_instantiate( + objects::class_value_wrapper< + held_type + , make_ptr_instance > + >() + ); + } + // + // Support for registering to-python converters + // + inline static void maybe_register_class_to_python(mpl::true_) {} + inline static void maybe_register_class_to_python(mpl::false_) + { + python::detail::force_instantiate(class_cref_wrapper >()); + } + + // + // Support for registering callback classes + // + inline static void maybe_register_callback_class(mpl::false_) {} + + inline static void maybe_register_callback_class(mpl::true_) + { + objects::register_shared_ptr_from_python_and_casts( + (wrapper*)0, mpl::single_view()); + + // explicit qualification of type_id makes msvc6 happy + objects::copy_class_object(python::type_id(), python::type_id()); + } +}; + +}}} // namespace boost::python::object + +#endif // CLASS_METADATA_DWA2004719_HPP diff --git a/include/boost/python/object/select_holder.hpp b/include/boost/python/object/select_holder.hpp deleted file mode 100644 index 11a8c09a..00000000 --- a/include/boost/python/object/select_holder.hpp +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright David Abrahams 2002. 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 SELECT_HOLDER_DWA2002322_HPP -# define SELECT_HOLDER_DWA2002322_HPP - -# include -# include -# include -# include -# include -# include -# include -# include -# include - -# include - -# include -# include -# include -# include - -# include -# include -# include - -# include - -namespace boost { namespace python { namespace objects { - -namespace detail -{ - - // check_default_constructible -- - // - // Used to give a clean error message when the user doesn't specify - // any __init__ functions, but when the class being wrapped doesn't - // have an appropriate default constructor (or if - // has_back_reference is true, a constructor taking PyObject*). - - // A helpful compile-time assertion which gives a reasonable error - // message if T can't be default-constructed. - template - static int specify_init_arguments_or_no_init_for_class_(T const&); - - // U is expected to take an initial hidden PyObject* in its - // constructor. Normally this means U is a virtual function - // dispatcher subclass for T. - template - void check_default_constructible(T*, U*, mpl::true_) - { - python::detail::force_instantiate( - sizeof(specify_init_arguments_or_no_init_for_class_(U((::PyObject*)0))) - ); - } - - // Handles the "normal" case where T is held directly and - // has_back_reference is not specialized. - template - void check_default_constructible(T*, T*, mpl::false_) - { - python::detail::force_instantiate( - sizeof(specify_init_arguments_or_no_init_for_class_(T())) - ); - } - - // - // select_value_holder/select_pointer_holder -- - // - // An instantiation of one of these data-free class templates is - // returned by select_holder::execute(), below. Each provides the - // following public interface: - // - // static void assert_default_constructible() -- called when no - // init<...> arguments are specified in class_'s - // constructor; causes a compile-time error when T has no - // corresponding default constructor. - // - // typedef ... type -- the class derived from instance_holder - // which will manage a Held object in Python class instances - // - // static type* get() { return 0; } -- just a way to access the - // computed type at runtime. - // - // static void register_() -- forces registration of any - // to_python converters corresponding to Held. - - template - struct select_value_holder - { - private: - typedef mpl::or_< - mpl::not_ > - , has_back_reference - > use_back_ref; - - public: - static void assert_default_constructible() - { - detail::check_default_constructible((T*)0,(Held*)0, use_back_ref()); - } - - typedef typename mpl::if_< - use_back_ref - , value_holder_back_reference - , value_holder - >::type type; - - typedef Held held_type; - - static inline void register_() {} - - static type* get() { return 0; } - }; - - template - struct select_pointer_holder - { - private: - typedef typename python::pointee::type wrapper; - typedef mpl::or_< - mpl::not_ > - , has_back_reference - > use_back_ref; - - public: - static void assert_default_constructible() - { - detail::check_default_constructible((T*)0,(wrapper*)0, use_back_ref()); - } - - typedef typename mpl::if_< - use_back_ref - , pointer_holder_back_reference - , pointer_holder - >::type type; - - typedef typename pointee::type held_type; - - static inline void register_() - { - select_pointer_holder::register_(use_back_ref()); - } - - static type* get() { return 0; } - - private: - static inline void register_(mpl::true_) - { - } - - struct construct_from_pointer - { - static type* execute(PyObject*, Ptr x) - { - return new type(x); - } - }; - - static inline void register_(mpl::false_) - { - python::detail::force_instantiate( - objects::class_value_wrapper >()); - } - }; -} - -// select_holder::execute((Held*)0) -// -// Returns an instantiation of -// detail::select_value_holder or detail::select_pointer_holder, as -// appropriate for class_ -template -struct select_holder - : mpl::if_< - is_same - , detail::select_value_holder - , typename mpl::if_< - mpl::or_< - is_same - , is_base_and_derived - > - , detail::select_value_holder - , detail::select_pointer_holder - >::type - >::type -{ -}; - -}}} // namespace boost::python::objects - -#endif // SELECT_HOLDER_DWA2002322_HPP diff --git a/include/boost/python/object_core.hpp b/include/boost/python/object_core.hpp index 733e09af..b133850d 100755 --- a/include/boost/python/object_core.hpp +++ b/include/boost/python/object_core.hpp @@ -39,6 +39,8 @@ # include # endif +# include + namespace boost { namespace python { namespace converter @@ -297,7 +299,14 @@ namespace api // explicit conversion from any C++ object to Python template - explicit object(T const& x) + explicit object( + T const& x +# if BOOST_WORKAROUND(BOOST_MSVC, == 1200) + // use some SFINAE to un-confuse MSVC about its + // copy-initialization ambiguity claim. + , typename mpl::if_,int&,int>::type* = 0 +# endif + ) : object_base(object_base_initializer(x)) { } diff --git a/include/boost/python/pure_virtual.hpp b/include/boost/python/pure_virtual.hpp index 860fff59..765d444c 100755 --- a/include/boost/python/pure_virtual.hpp +++ b/include/boost/python/pure_virtual.hpp @@ -91,7 +91,7 @@ namespace detail , options.policies() ); - typedef BOOST_DEDUCED_TYPENAME C_::select_holder::held_type held_t; + typedef BOOST_DEDUCED_TYPENAME C_::metadata::held_type held_type; // Add the default implementation which raises the exception c.def( @@ -99,7 +99,7 @@ namespace detail , make_function( detail::nullary_function_adaptor(pure_virtual_called) , default_call_policies() - , detail::error_signature(detail::get_signature(m_pmf)) + , detail::error_signature(detail::get_signature(m_pmf)) ) ); } diff --git a/include/boost/python/slice.hpp b/include/boost/python/slice.hpp index a48e80ba..90e9f51b 100644 --- a/include/boost/python/slice.hpp +++ b/include/boost/python/slice.hpp @@ -12,45 +12,55 @@ #include #include +#include + #include #include namespace boost { namespace python { -class BOOST_PYTHON_DECL slice : public object +namespace detail { - private: - // Helper function to work around bugs in MSVC 6 - static object new_slice(PyObject*, PyObject*, PyObject*); + class BOOST_PYTHON_DECL slice_base : public object + { + public: + // Get the Python objects associated with the slice. In principle, these + // may be any arbitrary Python type, but in practice they are usually + // integers. If one or more parameter is ommited in the Python expression + // that created this slice, than that parameter is None here, and compares + // equal to a default-constructed boost::python::object. + // If a user-defined type wishes to support slicing, then support for the + // special meaning associated with negative indicies is up to the user. + object start() const; + object stop() const; + object step() const; + + protected: + explicit slice_base(PyObject*, PyObject*, PyObject*); + BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(slice_base, object) + }; +} + +class slice : public detail::slice_base +{ + typedef detail::slice_base base; public: // Equivalent to slice(::) - slice(); + slice() : base(0,0,0) {} // Each argument must be slice_nil, or implicitly convertable to object. // They should normally be integers. template slice( Integer1 start, Integer2 stop) - : object( new_slice( object(start).ptr(), object(stop).ptr(), NULL)) + : base( object(start).ptr(), object(stop).ptr(), 0 ) {} template slice( Integer1 start, Integer2 stop, Integer3 stride) - : object( - new_slice( object(start).ptr(), object(stop).ptr(), object(stride).ptr())) + : base( object(start).ptr(), object(stop).ptr(), object(stride).ptr() ) {} - // Get the Python objects associated with the slice. In principle, these - // may be any arbitrary Python type, but in practice they are usually - // integers. If one or more parameter is ommited in the Python expression - // that created this slice, than that parameter is None here, and compares - // equal to a default-constructed boost::python::object. - // If a user-defined type wishes to support slicing, then support for the - // special meaning associated with negative indicies is up to the user. - object start() const; - object stop() const; - object step() const; - // The following algorithm is intended to automate the process of // determining a slice range when you want to fully support negative // indicies and non-singular step sizes. Its functionallity is simmilar to @@ -90,14 +100,12 @@ class BOOST_PYTHON_DECL slice : public object // the case where the user fails to catch the exception, it will simply // be translated to Python by the default exception handling mechanisms. - #ifndef BOOST_NO_MEMBER_TEMPLATES - template struct range { RandomAccessIterator start; RandomAccessIterator stop; - int step; + typename iterator_difference::type step; }; template @@ -109,9 +117,10 @@ class BOOST_PYTHON_DECL slice : public object // carefully crafted to ensure that these iterators never fall out of // the range of the container. slice::range ret; - typename RandomAccessIterator::difference_type max_dist = - std::distance( begin, end); - + + typedef typename iterator_difference::type difference_type; + difference_type max_dist = boost::detail::distance(begin, end); + object slice_start = this->start(); object slice_stop = this->stop(); object slice_step = this->step(); @@ -121,7 +130,7 @@ class BOOST_PYTHON_DECL slice : public object ret.step = 1; } else { - ret.step = extract( slice_step); + ret.step = extract( slice_step); if (ret.step == 0) { PyErr_SetString( PyExc_IndexError, "step size cannot be zero."); throw_error_already_set(); @@ -138,7 +147,7 @@ class BOOST_PYTHON_DECL slice : public object ret.start = begin; } else { - int i = extract( slice_start); + difference_type i = extract( slice_start); if (i >= max_dist && ret.step > 0) throw std::invalid_argument( "Zero-length slice"); if (i >= 0) { @@ -167,7 +176,7 @@ class BOOST_PYTHON_DECL slice : public object } } else { - int i = extract( slice_stop); + difference_type i = extract(slice_stop); // First, branch on which direction we are going with this. if (ret.step < 0) { if (i+1 >= max_dist || i == -1) @@ -188,8 +197,7 @@ class BOOST_PYTHON_DECL slice : public object if (i > 0) { ret.stop = begin; - BOOST_USING_STD_MIN(); - std::advance( ret.stop, min BOOST_PREVENT_MACRO_SUBSTITUTION( i-1, max_dist-1)); + std::advance( ret.stop, (std::min)( i-1, max_dist-1)); } else { // i is negative, but not more negative than -max_dist ret.stop = end; @@ -203,8 +211,8 @@ class BOOST_PYTHON_DECL slice : public object // represent the widest possible range that could be traveled // (inclusive), and final_dist is the maximum distance covered by the // slice. - typename RandomAccessIterator::difference_type final_dist = - std::distance( ret.start, ret.stop); + typename iterator_difference::type final_dist = + boost::detail::distance( ret.start, ret.stop); // First case, if both ret.start and ret.stop are equal, then step // is irrelevant and we can return here. @@ -222,24 +230,23 @@ class BOOST_PYTHON_DECL slice : public object // I don't remember all of the oolies surrounding negative modulii, // so I am handling each of these cases separately. if (final_dist < 0) { - int remainder = -final_dist % -ret.step; + difference_type remainder = -final_dist % -ret.step; std::advance( ret.stop, remainder); } else { - int remainder = final_dist % ret.step; + difference_type remainder = final_dist % ret.step; std::advance( ret.stop, -remainder); } return ret; } - #endif // !defined BOOST_NO_MEMBER_TEMPLATES public: // This declaration, in conjunction with the specialization of // object_manager_traits<> below, allows C++ functions accepting slice // arguments to be called from from Python. These constructors should never // be used in client code. - BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(slice, object) + BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(slice, detail::slice_base) }; diff --git a/src/slice.cpp b/src/slice.cpp index a4dd98f5..0b9d4721 100644 --- a/src/slice.cpp +++ b/src/slice.cpp @@ -6,39 +6,32 @@ // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -namespace boost { namespace python { +namespace boost { namespace python { namespace detail { -object -slice::new_slice(PyObject* start, PyObject* stop, PyObject* step) -{ - return object(detail::new_reference( PySlice_New(start, stop, step))); -} - -slice::slice() - : object( boost::python::detail::new_reference( - PySlice_New( NULL, NULL, NULL))) +slice_base::slice_base(PyObject* start, PyObject* stop, PyObject* step) + : object(detail::new_reference( PySlice_New(start, stop, step))) { } object -slice::start() const +slice_base::start() const { return object( detail::borrowed_reference( ((PySliceObject*)this->ptr())->start)); } object -slice::stop() const +slice_base::stop() const { return object( detail::borrowed_reference( ((PySliceObject*)this->ptr())->stop)); } object -slice::step() const +slice_base::step() const { return object( detail::borrowed_reference( ((PySliceObject*)this->ptr())->step)); } -} } // !namespace boost::python +} } } // !namespace boost::python::detail diff --git a/test/Jamfile b/test/Jamfile index 87f8688a..1a1e663d 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -158,7 +158,11 @@ bpl-test crossmod_exception [ bpl-test docstring ] [ bpl-test vector_indexing_suite ] -[ bpl-test map_indexing_suite ] + +[ extension map_indexing_suite_ext + : map_indexing_suite.cpp int_map_indexing_suite.cpp