diff --git a/include/boost/python/suite/indexing/container_suite.hpp b/include/boost/python/suite/indexing/container_suite.hpp index 3112e947..640736c1 100755 --- a/include/boost/python/suite/indexing/container_suite.hpp +++ b/include/boost/python/suite/indexing/container_suite.hpp @@ -17,6 +17,7 @@ // History // ======= // 2003/ 8/23 rmg File creation +// 2003/ 9/ 8 rmg Extracted trait facilities into container_traits.hpp // // $Id$ // @@ -24,325 +25,138 @@ #ifndef container_suite_rmg_20030823_included #define container_suite_rmg_20030823_included -#include "suite_utils.hpp" -#include "iterator_suite.hpp" -#include +#include "container_traits.hpp" +#include "slice_handler.hpp" -#include -#include -#include -#include -#include +#include +#include +#include +#include + +// #include namespace indexing { - ////////////////////////////////////////////////////////////////////////// - // Iterator pair container emulation - ////////////////////////////////////////////////////////////////////////// - - template - class iterator_pair - { - private: - typedef typename boost::call_traits::param_type iterator_param; - typedef std::iterator_traits std_traits; - - public: - typedef typename std_traits::reference reference; - typedef Iterator iterator; - typedef typename std_traits::difference_type size_type; - typedef typename std_traits::difference_type difference_type; - typedef typename std_traits::value_type value_type; - typedef typename std_traits::pointer pointer; - - // Can't provide: const_iterator, allocator_type, reverse_iterator - // or const_reverse_iterator. Could probably provide (but don't) - // const_reference and const_pointer. These would be the same - // as reference and pointer if Iterator is itself a const_iterator. - - public: - iterator_pair (iterator_param, iterator_param); - - iterator begin() const; - iterator end() const; - - public: - // Only sensible for random_access iterators - size_type size () const; - reference operator[] (size_type) const; - - private: - iterator myBegin; - iterator myEnd; + template + struct maybe_add_getitem { + template + static void apply (PythonClass &, Algorithms const &, Policy const &) { } }; - template - iterator_pair::iterator_pair (iterator_param begin - , iterator_param end) - : myBegin (begin) - , myEnd (end) - { - } - - template - typename iterator_pair::iterator - iterator_pair::begin() const - { - return myBegin; - } - - template - typename iterator_pair::iterator - iterator_pair::end() const - { - return myEnd; - } - - template - typename iterator_pair::size_type - iterator_pair::size() const - { - return std::distance (begin(), end()); - } - - template - typename iterator_pair::reference - iterator_pair::operator[](size_type index) const - { - return *(begin() + index); - } - - ///////////////////////////////////////////////////////////////////////// - // Container traits - ///////////////////////////////////////////////////////////////////////// - - ///////////////////////////////////////////////////////////////////////// - // Traits for the iterator_pair container emulator - ///////////////////////////////////////////////////////////////////////// - - template - struct iterator_pair_traits - : public - iterator_detail::traits_by_category::type - { - typedef IteratorPair container; - typedef typename IteratorPair::size_type size_type; - typedef typename IteratorPair::size_type index_type; // at() - - static bool const has_insert = false; - static bool const has_erase = false; - static bool const has_pop_back = false; - static bool const has_push_back = false; - - // Default implementations of support functions - typedef container_algorithms algorithms; + template<> + struct maybe_add_getitem { + template + static void apply (PythonClass &pyClass + , Algorithms const & + , Policy const &policy) + { + pyClass.def ("__getitem__", &Algorithms::get, policy); + } }; - ///////////////////////////////////////////////////////////////////////// - // Lowest common denominator (almost all "real" containers would - // meet at least these requirements) - ///////////////////////////////////////////////////////////////////////// - - template - struct default_container_traits - { - protected: - static bool const is_mutable = ! boost::is_const::value; - - public: - typedef Container container; - - typedef typename Container::value_type value_type; - typedef typename Container::reference reference; - typedef typename Container::difference_type difference_type; - typedef typename Container::size_type size_type; - typedef typename Container::size_type index_type; // at() - typedef value_type key_type; // find, count, ... - - // Should probably select iterator or const_iterator on the - // basis of is_mutable - typedef typename Container::iterator iterator; - typedef typename Container::const_iterator const_iterator; - - static bool const has_copyable_iter = true; - - static bool const has_random_access - = ::indexing::iterator_traits::has_random_access; - - static bool const has_mutable_ref - = is_mutable && is_mutable_ref::value; - - // has_mutable_ref basically means that the container supports - // in-place replacement of values (e.g. the associative containers - // *don't*) - - static bool const is_reversible = has_mutable_ref; - - static bool const has_insert = is_mutable; - static bool const has_erase = is_mutable; - static bool const has_pop_back = false; - static bool const has_push_back = false; - - // Default implementations of support functions - typedef container_algorithms algorithms; + template<> + struct maybe_add_getitem { + template + static void apply (PythonClass &pyClass + , Algorithms const & + , Policy const &policy) + { + pyClass.def ("__getitem__" + , slice_handler::make_getitem (policy)); + } }; - ///////////////////////////////////////////////////////////////////////// - // Sequences (list, deque, vector) - ///////////////////////////////////////////////////////////////////////// - - template - struct default_sequence_traits : public default_container_traits - { - static bool const has_pop_back = is_mutable; - static bool const has_push_back = is_mutable; + template + struct maybe_add_setitem { + template + static void apply (PythonClass &, Algorithms const &, Policy const &) { } }; - template - struct list_traits : public default_sequence_traits - { - // Some special algo's for list (using member functions) - typedef list_algorithms algorithms; + template<> + struct maybe_add_setitem { + template + static void apply (PythonClass &pyClass + , Algorithms const & + , Policy const &policy) + { + pyClass.def ("__setitem__", &Algorithms::assign, policy); + } }; - ///////////////////////////////////////////////////////////////////////// - // Associative containers set and multiset - ///////////////////////////////////////////////////////////////////////// - - template - struct set_traits : public default_container_traits - { - // Special algo's for set types (using member functions) - typedef assoc_algorithms algorithms; + template<> + struct maybe_add_setitem { + template + static void apply (PythonClass &pyClass + , Algorithms const & + , Policy const &policy) + { + pyClass.def ("__setitem__", &Algorithms::assign, policy); + // *FIXME* add slicing support + } }; - ///////////////////////////////////////////////////////////////////////// - // Associative containers map and multimap - ///////////////////////////////////////////////////////////////////////// - - template - struct map_traits : public default_container_traits - { - typedef typename Container::key_type key_type; // find, count, ... - - // Special algo's for map types (using member functions) - typedef assoc_algorithms algorithms; + template + struct maybe_add_iter { + template + static void apply (PythonClass &, Algorithms const &, Policy const &) { } }; - ///////////////////////////////////////////////////////////////////////// - // Automated trait selection - ///////////////////////////////////////////////////////////////////////// - - namespace container_details { - template struct traits_by_type; - - // traits_by_type instances should include two typedefs, one for - // the non-const version of the container, and one for the - // const version. This saves having to have two specializations - // of traits_by_type for every kind of container. - - // std::set - template - class traits_by_type > + template<> + struct maybe_add_iter { + template + static void apply (PythonClass &pyClass + , Algorithms const & + , Policy const &policy) { - typedef std::set Container; - - public: - typedef set_traits mutable_type; - typedef set_traits const_type; - }; - - // std::multiset - template - class traits_by_type > - { - typedef std::multiset Container; - - public: - typedef set_traits mutable_type; - typedef set_traits const_type; - }; - - // std::map - template - class traits_by_type > - { - typedef std::map Container; - - public: - typedef map_traits mutable_type; - typedef map_traits const_type; - }; - - // std::multimap - template - class traits_by_type > - { - typedef std::multimap Container; - - public: - typedef map_traits mutable_type; - typedef map_traits const_type; - }; - - // std::vector - template - class traits_by_type > - { - typedef std::vector Container; - - public: - typedef default_sequence_traits mutable_type; - typedef default_sequence_traits const_type; - }; - - // std::deque - template - class traits_by_type > - { - typedef std::deque Container; - - public: - typedef default_sequence_traits mutable_type; - typedef default_sequence_traits const_type; - }; - - // std::list - template - class traits_by_type > - { - typedef std::list Container; - - public: - typedef list_traits mutable_type; - typedef list_traits const_type; - }; - - // Iterator ranges - template - class traits_by_type > - { - typedef ::indexing::iterator_pair Container; - - public: - typedef iterator_pair_traits mutable_type; - typedef iterator_pair_traits const_type; // ? - }; - } - - // Select the right traits for each supported kind of container - - // Generic version (mutable containers) - template - struct container_traits - : public container_details::traits_by_type::mutable_type - { + pyClass.def ("__iter__" + , boost::python::range (Algorithms::begin + , Algorithms::end)); + } }; - // Partial specialization for const containers - template - struct container_traits - : public container_details::traits_by_type::const_type + template + struct maybe_add_append { + template + static void apply (PythonClass &, Algorithms const &, Policy const &) { } + }; + + template<> + struct maybe_add_append { + template + static void apply (PythonClass &pyClass + , Algorithms const & + , Policy const &policy) + { + pyClass.def ("append", &Algorithms::push_back, policy); + } + }; + + template > + struct container_suite + : public boost::python::def_visitor > { + typedef typename Traits::algorithms algorithms; + typedef typename Traits::reference reference_return; + + typedef boost::python::return_value_policy + return_policy; + + template + static void visit (PythonClass &pyClass) + { + maybe_add_getitem + ::apply (pyClass, algorithms(), return_policy()); + + maybe_add_setitem + ::apply (pyClass, algorithms(), return_policy()); + + maybe_add_iter<((Traits::index_style != index_style_linear) + && Traits::has_copyable_iter)> + ::apply (pyClass, algorithms(), return_policy()); + + maybe_add_append + ::apply (pyClass, algorithms(), return_policy()); + } }; }