2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-24 18:12:43 +00:00

MSVC6 and 7 compatibility fixes

[SVN r20779]
This commit is contained in:
Raoul Gough
2003-11-10 18:06:41 +00:00
parent 997467c29f
commit 91db6f2d50
34 changed files with 773 additions and 284 deletions

View File

@@ -21,9 +21,19 @@
#ifndef BOOST_PYTHON_INDEXING_ALGO_SELECTOR_HPP
#define BOOST_PYTHON_INDEXING_ALGO_SELECTOR_HPP
#include <boost/detail/workaround.hpp>
namespace boost { namespace python { namespace indexing {
namespace detail {
template<typename Container> class selector_impl;
template<typename Container> class selector_impl
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
{
// Bogus types to prevent compile errors due to ETI
typedef selector_impl<Container> mutable_algorithms;
typedef selector_impl<Container> const_algorithms;
}
#endif
;
// selector_impl specializations should include *two* publically
// accessible typedefs, called mutable_algorithms and
@@ -41,12 +51,14 @@ namespace boost { namespace python { namespace indexing {
{
};
#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
// Partial specialization for const containers
template<class Container>
struct algo_selector<Container const>
: public detail::selector_impl<Container>::const_algorithms
{
};
#endif
} } }
#endif // BOOST_PYTHON_INDEXING_ALGO_SELECTOR_HPP

View File

@@ -53,7 +53,8 @@ namespace boost { namespace python { namespace indexing {
class default_algorithms
{
typedef default_algorithms<ContainerTraits, Ovr> self_type;
typedef typename detail::maybe_override<self_type, Ovr>::type most_derived;
typedef typename detail::maybe_override<self_type, Ovr>
::type most_derived;
public:
typedef ContainerTraits container_traits;
@@ -93,9 +94,18 @@ namespace boost { namespace python { namespace indexing {
// Default visitor_helper
template<typename PythonClass, typename Policy>
static void visitor_helper (PythonClass &, Policy const &);
static void visitor_helper (PythonClass &pyClass, Policy const &policy)
{
container_traits::visitor_helper (pyClass, policy);
}
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
// MSVC6 and 7.0 seem to complain about most_derived::bounds_check
// for an instantiation of list_algorithms.
public:
#else
private:
#endif
static size_type bounds_check (
container &, index_param, char const *msg
, bool one_past = false
@@ -116,12 +126,13 @@ namespace boost { namespace python { namespace indexing {
class assoc_algorithms
: public default_algorithms
<ContainerTraits
, typename detail::maybe_override
, BOOST_DEDUCED_TYPENAME detail::maybe_override
<assoc_algorithms<ContainerTraits, Ovr>, Ovr>
::type>
{
typedef assoc_algorithms<ContainerTraits, Ovr> self_type;
typedef typename detail::maybe_override<self_type, Ovr>::type most_derived;
typedef typename detail::maybe_override<self_type, Ovr>
::type most_derived;
typedef default_algorithms<ContainerTraits, most_derived> Parent;
public:
@@ -150,7 +161,7 @@ namespace boost { namespace python { namespace indexing {
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits, typename Ovr>
typename default_algorithms<ContainerTraits, Ovr>::size_type
BOOST_DEDUCED_TYPENAME default_algorithms<ContainerTraits, Ovr>::size_type
default_algorithms<ContainerTraits, Ovr>::size (container &c)
{
return c.size();
@@ -161,7 +172,7 @@ namespace boost { namespace python { namespace indexing {
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits, typename Ovr>
typename default_algorithms<ContainerTraits, Ovr>::size_type
BOOST_DEDUCED_TYPENAME default_algorithms<ContainerTraits, Ovr>::size_type
default_algorithms<ContainerTraits, Ovr>::bounds_check (
container &c
, index_param ix
@@ -218,7 +229,7 @@ namespace boost { namespace python { namespace indexing {
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits, typename Ovr>
typename default_algorithms<ContainerTraits, Ovr>::iterator
BOOST_DEDUCED_TYPENAME default_algorithms<ContainerTraits, Ovr>::iterator
default_algorithms<ContainerTraits, Ovr>::find (
container &c, key_param key)
{
@@ -230,13 +241,13 @@ namespace boost { namespace python { namespace indexing {
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits, typename Ovr>
typename default_algorithms<ContainerTraits, Ovr>::size_type
BOOST_DEDUCED_TYPENAME default_algorithms<ContainerTraits, Ovr>::size_type
default_algorithms<ContainerTraits, Ovr>::get_index (
container &c, key_param key)
{
iterator temp (most_derived::find (c, key));
iterator found (most_derived::find (c, key));
if (temp == most_derived::end(c))
if (found == most_derived::end(c))
{
PyErr_SetString (
PyExc_ValueError, "get_index: element not found");
@@ -244,7 +255,8 @@ namespace boost { namespace python { namespace indexing {
boost::python::throw_error_already_set ();
}
return std::distance (most_derived::begin (c), temp);
iterator start (most_derived::begin (c));
return std::distance (start, found);
}
/////////////////////////////////////////////////////////////////////////
@@ -252,7 +264,7 @@ namespace boost { namespace python { namespace indexing {
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits, typename Ovr>
typename default_algorithms<ContainerTraits, Ovr>::size_type
BOOST_DEDUCED_TYPENAME default_algorithms<ContainerTraits, Ovr>::size_type
default_algorithms<ContainerTraits, Ovr>::count (
container &c, key_param key)
{
@@ -276,7 +288,7 @@ namespace boost { namespace python { namespace indexing {
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits, typename Ovr>
typename default_algorithms<ContainerTraits, Ovr>::reference
BOOST_DEDUCED_TYPENAME default_algorithms<ContainerTraits, Ovr>::reference
default_algorithms<ContainerTraits, Ovr>::get (
container &c, index_param ix)
{
@@ -387,32 +399,19 @@ namespace boost { namespace python { namespace indexing {
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits, typename Ovr>
typename default_algorithms<ContainerTraits, Ovr>::slice_helper
BOOST_DEDUCED_TYPENAME default_algorithms<ContainerTraits, Ovr>::slice_helper
default_algorithms<ContainerTraits, Ovr>
::make_slice_helper (container &c, slice const &sl)
{
return slice_helper (c, integer_slice (sl, most_derived::size (c)));
}
/////////////////////////////////////////////////////////////////////////
// Visitor helper function (default version)
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits, typename Ovr>
template<typename PythonClass, typename Policy>
void
default_algorithms<ContainerTraits, Ovr>
::visitor_helper (PythonClass &pyClass, Policy const &policy)
{
container_traits::visitor_helper (pyClass, policy);
}
/////////////////////////////////////////////////////////////////////////
// Index into a container (associative version)
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits, typename Ovr>
typename assoc_algorithms<ContainerTraits, Ovr>::reference
BOOST_DEDUCED_TYPENAME assoc_algorithms<ContainerTraits, Ovr>::reference
assoc_algorithms<ContainerTraits, Ovr>::get (container &c, index_param ix)
{
return *most_derived::find_or_throw (c, ix);
@@ -441,7 +440,7 @@ namespace boost { namespace python { namespace indexing {
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits, typename Ovr>
typename assoc_algorithms<ContainerTraits, Ovr>::iterator
BOOST_DEDUCED_TYPENAME assoc_algorithms<ContainerTraits, Ovr>::iterator
assoc_algorithms<ContainerTraits, Ovr>
::find (container &c, key_param key)
{
@@ -466,7 +465,7 @@ namespace boost { namespace python { namespace indexing {
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits, typename Ovr>
typename assoc_algorithms<ContainerTraits, Ovr>::iterator
BOOST_DEDUCED_TYPENAME assoc_algorithms<ContainerTraits, Ovr>::iterator
assoc_algorithms<ContainerTraits, Ovr>::find_or_throw (
container &c, index_param ix)
{
@@ -488,7 +487,7 @@ namespace boost { namespace python { namespace indexing {
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits, typename Ovr>
typename assoc_algorithms<ContainerTraits, Ovr>::size_type
BOOST_DEDUCED_TYPENAME assoc_algorithms<ContainerTraits, Ovr>::size_type
assoc_algorithms<ContainerTraits, Ovr>::count (
container &c, key_param key)
{

View File

@@ -36,6 +36,7 @@
#include <boost/shared_ptr.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <boost/python/suite/indexing/container_traits.hpp>
#include <boost/python/suite/indexing/container_suite.hpp>
#include <boost/python/suite/indexing/algorithms.hpp>
#include <boost/python/suite/indexing/algo_selector.hpp>
@@ -82,8 +83,11 @@ namespace boost { namespace python { namespace indexing {
typedef typename Container::iterator raw_iterator;
typedef ::boost::detail::iterator_traits<raw_iterator> raw_iterator_traits;
#if !defined (BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template<class C> friend class shared_proxy_impl;
template<class C> friend class proxy_iterator;
template<class C, typename E, typename T, typename S, typename I>
friend class proxy_iterator;
#endif
public:
typedef typename Holder::held_type held_type;
@@ -101,14 +105,22 @@ namespace boost { namespace python { namespace indexing {
typedef const_element_proxy<self_type> const_value_type;
typedef const_value_type const_reference; // Ref. semantics
typedef proxy_iterator<self_type> iterator;
typedef proxy_iterator<self_type> const_iterator; // ??
typedef proxy_iterator <self_type, value_type, raw_iterator_traits
, size_type, raw_iterator> iterator;
typedef iterator const_iterator; // No const_iterator yet implemented
public:
// Constructors
template<typename Iter> container_proxy (Iter start, Iter finish)
// Define inline for MSVC6 compatibility
: m_held_obj (Holder::create())
, m_proxies ()
{
insert (begin(), start, finish);
}
container_proxy ();
explicit container_proxy (held_type const &h);
template<typename Iter> container_proxy (Iter, Iter);
container_proxy (container_proxy const &);
container_proxy &operator= (container_proxy const &);
@@ -133,7 +145,14 @@ namespace boost { namespace python { namespace indexing {
iterator erase (iterator);
iterator erase (iterator, iterator);
iterator insert (iterator, raw_value_type const &);
template<typename Iter> void insert (iterator, Iter, Iter);
template<typename Iter> void insert (iterator iter, Iter from, Iter to)
// Define here for MSVC6 compatibility
{
// Forward insertion to the right overloaded version
typedef typename BOOST_ITERATOR_CATEGORY<Iter>::type category;
insert (iter, from, to, category());
}
void push_back (raw_value_type const &copy) { insert (end(), copy); }
@@ -163,7 +182,7 @@ namespace boost { namespace python { namespace indexing {
public:
// Convenient replacement of elements (automatic proxy detachment)
void replace (size_type index, raw_value_type const &);
template<typename Iter> void replace (size_type index, Iter, Iter);
// template<typename Iter> void replace (size_type index, Iter, Iter);
void swap_elements (size_type index1, size_type index2);
@@ -172,20 +191,87 @@ namespace boost { namespace python { namespace indexing {
private:
// Overloads for insertions with/without useful std::distance
template<typename Iter>
void insert (iterator, Iter, Iter, std::forward_iterator_tag);
void insert (iterator iter, Iter from, Iter to, std::forward_iterator_tag)
// Define here for MSVC6 compatibility
{
assert (iter.ptr == this);
size_type count = std::distance (from, to);
// Add empty proxy pointers for the new value(s) (could throw)
m_proxies.insert (m_proxies.begin() + iter.index, count, pointer_impl());
try
{
// Insert the new element(s) into the real container (could throw)
raw_container().insert (
raw_container().begin() + iter.index
, from
, to);
try
{
// Create new proxies for the new elements (could throw)
write_proxies (iter.index, iter.index + count);
}
catch (...)
{
raw_container().erase (
raw_container().begin() + iter.index
, raw_container().begin() + iter.index + count);
throw;
}
}
catch (...)
{
m_proxies.erase (
m_proxies.begin() + iter.index
, m_proxies.begin() + iter.index + count);
throw;
}
// Adjust any proxies after the inserted elements (nothrow)
adjust_proxies (
m_proxies.begin() + iter.index + count
, m_proxies.end()
, static_cast<difference_type> (count));
}
template<typename Iter>
void insert (iterator, Iter, Iter, std::input_iterator_tag);
void insert (iterator iter, Iter from, Iter to, std::input_iterator_tag)
// Define here for MSVC6 compatibility
{
// insert overload for iterators where we *can't* get distance()
// so just insert elements one at a time
while (from != to)
{
iter = insert (iter, *from++) + 1;
}
}
private:
typedef boost::shared_ptr<shared_proxy> pointer_impl;
typedef typename Generator::template apply<pointer_impl>::type
pointer_container;
#if defined (BOOST_NO_MEMBER_TEMPLATES) \
&& defined (BOOST_MSVC6_MEMBER_TEMPLATES)
// Ignore the Generator argument, to avoid an MSVC6 fatal error
// (C1001 internal compiler error).
typedef std::vector<pointer_impl> pointer_container;
#else
typedef typename Generator::BOOST_PYTHON_INDEXING_NESTED_TEMPLATE
apply<pointer_impl>::type pointer_container;
#endif
typedef typename pointer_container::iterator pointer_iterator;
private:
#if defined (BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
// Proxies need mutable access, and can't be friends with MSVC6
public:
#endif
Container &raw_container();
private:
void adjust_proxies (pointer_iterator, pointer_iterator, difference_type);
void write_proxies (size_type, size_type);
bool clear_proxy (pointer_impl &); // detach and do not reset
@@ -214,6 +300,7 @@ namespace boost { namespace python { namespace indexing {
write_proxies (0, size());
}
/*
template<class Container, class Holder, class Generator>
template<typename Iter>
container_proxy<Container, Holder, Generator>
@@ -223,6 +310,7 @@ namespace boost { namespace python { namespace indexing {
{
insert (begin(), start, finish);
}
*/
template<class Container, class Holder, class Generator>
container_proxy<Container, Holder, Generator>
@@ -238,6 +326,8 @@ namespace boost { namespace python { namespace indexing {
container_proxy<Container, Holder, Generator>
::operator= (container_proxy const &copy)
{
// *FIXME* - provide an exception safety guarantee
// Copy original values into any proxies being shared by external pointers
clear_proxies (0, size());
@@ -282,22 +372,22 @@ namespace boost { namespace python { namespace indexing {
}
template<class Container, class Holder, class Generator>
typename container_proxy<Container, Holder, Generator>::reference
BOOST_DEDUCED_TYPENAME container_proxy<Container, Holder, Generator>::reference
container_proxy<Container, Holder, Generator>
::at (size_type index)
{
pointer_impl const &ptr (m_proxies.BOOST_INDEXING_AT (index));
pointer_impl const &ptr = m_proxies.BOOST_PYTHON_INDEXING_AT (index);
assert (ptr->owner() == this);
assert (ptr->index() == index);
return reference (ptr);
}
template<class Container, class Holder, class Generator>
typename container_proxy<Container, Holder, Generator>::const_reference
BOOST_DEDUCED_TYPENAME container_proxy<Container, Holder, Generator>::const_reference
container_proxy<Container, Holder, Generator>
::at (size_type index) const
{
pointer_impl const &ptr (m_proxies.BOOST_INDEXING_AT (index));
pointer_impl const &ptr (m_proxies.BOOST_PYTHON_INDEXING_AT (index));
assert (ptr->owner() == this);
assert (ptr->index() == index);
return const_reference (ptr);
@@ -309,10 +399,11 @@ namespace boost { namespace python { namespace indexing {
::replace (size_type index, raw_value_type const &copy)
{
detach_proxy (index);
raw_container().BOOST_INDEXING_AT (index) = copy;
raw_container().BOOST_PYTHON_INDEXING_AT (index) = copy;
write_proxies (index, index + 1);
}
/*
template<class Container, class Holder, class Generator>
template<typename Iter>
void
@@ -324,14 +415,15 @@ namespace boost { namespace python { namespace indexing {
replace (index++, *from++);
}
}
*/
template<class Container, class Holder, class Generator>
void
container_proxy<Container, Holder, Generator>
::swap_elements (size_type index1, size_type index2)
{
pointer_impl &ptr1 (m_proxies[index1]);
pointer_impl &ptr2 (m_proxies[index2]);
pointer_impl &ptr1 = m_proxies[index1];
pointer_impl &ptr2 = m_proxies[index2];
assert (ptr1->owner() == this);
assert (ptr2->owner() == this);
@@ -363,14 +455,14 @@ namespace boost { namespace python { namespace indexing {
}
template<class Container, class Holder, class Generator>
typename container_proxy<Container, Holder, Generator>::iterator
BOOST_DEDUCED_TYPENAME container_proxy<Container, Holder, Generator>::iterator
container_proxy<Container, Holder, Generator>::erase (iterator iter)
{
return erase (iter, iter + 1);
}
template<class Container, class Holder, class Generator>
typename container_proxy<Container, Holder, Generator>::iterator
BOOST_DEDUCED_TYPENAME container_proxy<Container, Holder, Generator>::iterator
container_proxy<Container, Holder, Generator>::erase (
iterator from, iterator to)
{
@@ -389,6 +481,7 @@ namespace boost { namespace python { namespace indexing {
return iterator (this, result);
}
/*
template<class Container, class Holder, class Generator>
template<typename Iter>
void container_proxy<Container, Holder, Generator>::insert (
@@ -440,18 +533,6 @@ namespace boost { namespace python { namespace indexing {
, static_cast<difference_type> (count));
}
template<class Container, class Holder, class Generator>
typename container_proxy<Container, Holder, Generator>::iterator
container_proxy<Container, Holder, Generator>::insert (
iterator iter, raw_value_type const &copy)
{
// Use the iterator-based version by treating the value as an
// array of size one (see section 5.7/4 of the C++98 standard)
insert (iter, &copy, (&copy) + 1, std::random_access_iterator_tag());
return iter;
}
template<class Container, class Holder, class Generator>
template<typename Iter>
void container_proxy<Container, Holder, Generator>::insert (
@@ -474,6 +555,19 @@ namespace boost { namespace python { namespace indexing {
typedef typename BOOST_ITERATOR_CATEGORY<Iter>::type category;
insert (iter, from, to, category());
}
*/
template<class Container, class Holder, class Generator>
BOOST_DEDUCED_TYPENAME container_proxy<Container, Holder, Generator>::iterator
container_proxy<Container, Holder, Generator>::insert (
iterator iter, raw_value_type const &copy)
{
// Use the iterator-based version by treating the value as an
// array of size one (see section 5.7/4 of the C++98 standard)
insert (iter, &copy, (&copy) + 1, std::random_access_iterator_tag());
return iter;
}
template<class Container, class Holder, class Generator>
bool container_proxy<Container, Holder, Generator>::clear_proxy (
@@ -514,7 +608,7 @@ namespace boost { namespace python { namespace indexing {
void container_proxy<Container, Holder, Generator>
::detach_proxy (size_type index)
{
pointer_impl &ptr (m_proxies[index]);
pointer_impl &ptr = m_proxies[index];
assert (ptr->index() == index);
@@ -608,7 +702,7 @@ namespace boost { namespace python { namespace indexing {
while (from != to)
{
pointer_impl &ptr (m_proxies[from]);
pointer_impl &ptr = m_proxies[from];
if ((ptr.get() == 0) || (!ptr.unique()))
{
@@ -635,7 +729,7 @@ namespace boost { namespace python { namespace indexing {
for (size_type count = 0; ok && (count < size()); ++count)
{
pointer_impl const &ptr (m_proxies[count]);
pointer_impl const &ptr = m_proxies[count];
ok = ptr.get() && (ptr->owner() == this) && (ptr->index() == count)
&& !ptr->m_element_ptr.get();
@@ -654,19 +748,33 @@ namespace boost { namespace python { namespace indexing {
typedef Container container;
typedef typename container::raw_value_type value_type; // insert, ...
typedef typename container::raw_value_type key_type; // find, count, ...
typedef typename container::reference reference; // return values
typedef typename container::reference reference; // return values
typedef typename boost::call_traits<value_type>::param_type value_param;
typedef typename boost::call_traits<key_type>::param_type key_param;
typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <value_type>::param_type
value_param;
typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <key_type>::param_type
key_param;
#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
typedef value_traits<reference> value_traits_;
#else
typedef element_proxy_traits<Container> value_traits_;
// Forward visitor_helper to eleemnt_proxy_traits
template<typename PythonClass, typename Policy>
static void visitor_helper (PythonClass &pyClass, Policy const &policy)
{
value_traits_::visitor_helper (pyClass, policy);
}
#endif
// Get value_traits for the reference type (i.e. element_proxy)
// to get the custom visitor_helper
};
#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
namespace detail {
///////////////////////////////////////////////////////////////////////
// algo_selector support for std::list instances
// algo_selector support for container_proxy instances
///////////////////////////////////////////////////////////////////////
template <typename RawContainer, typename Holder, typename Generator>
@@ -682,6 +790,13 @@ namespace boost { namespace python { namespace indexing {
typedef default_algorithms<const_traits> const_algorithms;
};
}
#endif
template<class Container, class Traits = container_proxy_traits<Container> >
struct container_proxy_suite
: container_suite<Container, default_algorithms<Traits> >
{
};
} } }
#endif // BOOST_PYTHON_INDEXING_CONTAINER_PROXY_HPP

View File

@@ -29,7 +29,11 @@ namespace boost { namespace python { namespace indexing {
typedef boost::python::return_value_policy<boost::python::return_by_value>
default_container_policies;
template<class Container, class Algorithms = algo_selector<Container> >
template <
class Container
, class Algorithms
= algo_selector<Container>
>
struct container_suite
: public visitor<Algorithms, default_container_policies>
{

View File

@@ -28,8 +28,25 @@
#include <boost/type_traits.hpp>
#include <boost/call_traits.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/ice.hpp>
#define ICE_AND(a, b) type_traits::ice_and<(a), (b)>::value
namespace boost { namespace python { namespace indexing {
#if BOOST_WORKAROUND (BOOST_MSVC, <= 1200)
// MSVC6 has problems with get_signature if parameter types have
// top-level const qualification (e.g. int const). Unfortunately,
// this is exactly what happens with boost::call_traits, so we
// substitute a really dumb version of it instead.
template<typename T> struct broken_call_traits {
typedef T const & param_type;
};
# define BOOST_PYTHON_INDEXING_CALL_TRAITS broken_call_traits
#else
# define BOOST_PYTHON_INDEXING_CALL_TRAITS ::boost::call_traits
#endif
/////////////////////////////////////////////////////////////////////////
// Lowest common denominator traits - applicable to real containers
// and iterator pairs
@@ -38,19 +55,19 @@ namespace boost { namespace python { namespace indexing {
template<typename Container>
struct base_container_traits
: public ::boost::python::indexing::iterator_traits <
typename mpl::if_ <
BOOST_DEDUCED_TYPENAME mpl::if_ <
is_const<Container>
, typename Container::const_iterator
, typename Container::iterator
, BOOST_DEDUCED_TYPENAME Container::const_iterator
, BOOST_DEDUCED_TYPENAME Container::iterator
>::type
>
{
protected:
typedef ::boost::python::indexing::iterator_traits <
typename mpl::if_ <
BOOST_DEDUCED_TYPENAME mpl::if_ <
is_const<Container>
, typename Container::const_iterator
, typename Container::iterator
, BOOST_DEDUCED_TYPENAME Container::const_iterator
, BOOST_DEDUCED_TYPENAME Container::iterator
>::type
> base_type;
@@ -61,20 +78,23 @@ namespace boost { namespace python { namespace indexing {
typedef Container container;
typedef typename container::size_type size_type;
typedef typename base_type::value_type value_type; // insert, etc.
typedef typename base_type::value_type key_type; // find, count, ...
typedef typename base_type::value_type value_type; // insert
typedef typename base_type::value_type key_type; // find
typedef typename make_signed<size_type>::type index_type;
// at(), operator[]. Signed to support Python -ve indexes
typedef typename boost::call_traits<value_type>::param_type value_param;
typedef typename boost::call_traits<key_type>::param_type key_param;
typedef typename boost::call_traits<index_type>::param_type index_param;
typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <value_type>::param_type
value_param;
typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <key_type>::param_type
key_param;
typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <index_type>::param_type
index_param;
typedef value_traits<typename base_type::value_type> value_traits_;
BOOST_STATIC_CONSTANT (bool, has_mutable_ref
= base_type::has_mutable_ref && is_mutable);
= ICE_AND (base_type::has_mutable_ref, is_mutable));
BOOST_STATIC_CONSTANT (bool, has_find
= value_traits_::equality_comparable);
@@ -87,7 +107,10 @@ namespace boost { namespace python { namespace indexing {
// Forward visitor_helper to value_traits_
template<typename PythonClass, typename Policy>
static void visitor_helper (PythonClass &, Policy const &);
static void visitor_helper (PythonClass &pyClass, Policy const &policy)
{
value_traits_::visitor_helper (pyClass, policy);
}
};
/////////////////////////////////////////////////////////////////////////
@@ -117,17 +140,4 @@ namespace boost { namespace python { namespace indexing {
} } }
/////////////////////////////////////////////////////////////////////////
// Visitor helper function (foward to value_traits_ version)
/////////////////////////////////////////////////////////////////////////
template<typename Container>
template<typename PythonClass, typename Policy>
void
boost::python::indexing::base_container_traits<Container>
::visitor_helper (PythonClass &pyClass, Policy const &policy)
{
value_traits_::visitor_helper (pyClass, policy);
}
#endif // BOOST_PYTHON_INDEXING_CONTAINER_SUITE_HPP

View File

@@ -19,11 +19,13 @@
#define BOOST_PYTHON_INDEXING_DEQUE_HPP
#include <boost/python/suite/indexing/container_traits.hpp>
#include <boost/python/suite/indexing/container_suite.hpp>
#include <boost/python/suite/indexing/algorithms.hpp>
#include <boost/python/suite/indexing/algo_selector.hpp>
#include <deque>
namespace boost { namespace python { namespace indexing {
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
namespace detail {
///////////////////////////////////////////////////////////////////////
// algo_selector support for std::deque instances
@@ -42,6 +44,12 @@ namespace boost { namespace python { namespace indexing {
typedef default_algorithms<const_traits> const_algorithms;
};
}
#endif
template<class Container, class Traits = default_sequence_traits<Container> >
struct deque_suite : container_suite<Container, default_algorithms<Traits> >
{
};
} } }

View File

@@ -1,4 +1,3 @@
//
// Header file element_proxy.hpp
//
// Proxy objects for invidivual elements in a container wrapped by
@@ -28,13 +27,17 @@ namespace boost { namespace python { namespace indexing {
template<typename ContainerProxy>
class element_proxy
{
#if defined (BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
public:
#else
template<typename T> friend struct const_element_proxy;
#endif
typedef ContainerProxy container_proxy;
typedef typename container_proxy::shared_proxy proxy_type;
typedef ContainerProxy container_proxy_;
typedef typename container_proxy_::shared_proxy proxy_type;
typedef boost::shared_ptr<proxy_type> proxy_pointer;
typedef typename container_proxy::raw_value_type raw_value_type;
typedef typename container_proxy::size_type size_type;
typedef typename container_proxy_::raw_value_type raw_value_type;
typedef typename container_proxy_::size_type size_type;
proxy_pointer m_ptr;
@@ -76,8 +79,8 @@ namespace boost { namespace python { namespace indexing {
element_proxy &operator= (value_type const &copy)
{
proxy_type &proxy (*m_ptr);
container_proxy *container = proxy.owner();
proxy_type &proxy = *m_ptr;
container_proxy_ *container = proxy.owner();
size_type index = proxy.index();
if (container)
@@ -117,10 +120,10 @@ namespace boost { namespace python { namespace indexing {
template<typename ContainerProxy>
struct const_element_proxy
{
typedef ContainerProxy container_proxy;
typedef typename container_proxy::shared_proxy proxy_type;
typedef ContainerProxy container_proxy_;
typedef typename container_proxy_::shared_proxy proxy_type;
typedef boost::shared_ptr<proxy_type> proxy_pointer;
typedef typename container_proxy::raw_value_type raw_value_type;
typedef typename container_proxy_::raw_value_type raw_value_type;
proxy_pointer m_ptr;
@@ -135,7 +138,7 @@ namespace boost { namespace python { namespace indexing {
explicit const_element_proxy (proxy_type *ptr) : m_ptr (ptr) { }
const_element_proxy (proxy_pointer const &ptr) : m_ptr (ptr) { }
const_element_proxy (element_proxy<container_proxy> const &copy)
const_element_proxy (element_proxy<container_proxy_> const &copy)
: m_ptr (copy.m_ptr)
{
}

View File

@@ -23,9 +23,17 @@
#include <boost/python/implicit.hpp>
namespace boost { namespace python { namespace indexing {
#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
template<typename ContainerProxy>
struct value_traits<element_proxy<ContainerProxy> >
: public value_traits<typename ContainerProxy::raw_value_type>
: public value_traits <
BOOST_DEDUCED_TYPENAME ContainerProxy::raw_value_type>
#else
template<typename ContainerProxy>
struct element_proxy_traits
: public value_traits <
BOOST_DEDUCED_TYPENAME ContainerProxy::raw_value_type>
#endif
{
template<typename PythonClass, typename Policy>
static void visitor_helper (PythonClass &, Policy const &)

View File

@@ -18,7 +18,8 @@
#ifndef BOOST_PYTHON_INDEXING_INT_SLICE_HELPER_HPP
#define BOOST_PYTHON_INDEXING_INT_SLICE_HELPER_HPP
#include <boost/python/errors.hpp>
# include <boost/python/errors.hpp>
# include <boost/python/suite/indexing/workaround.hpp>
namespace boost { namespace python { namespace indexing {
template<typename Algorithms, typename SliceType>
@@ -117,6 +118,13 @@ namespace boost { namespace python { namespace indexing {
template<bool doit> struct maybe_insert {
template<class Algorithms>
static void apply (
# if defined (BOOST_NO_MEMBER_TEMPLATES) \
&& defined (BOOST_MSVC6_MEMBER_TEMPLATES)
// Can't explicitly instantiate member function - must let
// the compiler deduce the argument type from a dummy
// parameter. Same applies throughout
Algorithms *,
# endif
typename Algorithms::container &
, typename Algorithms::index_param
, typename Algorithms::value_param)
@@ -132,6 +140,10 @@ namespace boost { namespace python { namespace indexing {
template<> struct maybe_insert<true> {
template<class Algorithms>
static void apply (
# if defined (BOOST_NO_MEMBER_TEMPLATES) \
&& defined (BOOST_MSVC6_MEMBER_TEMPLATES)
Algorithms *,
# endif
typename Algorithms::container &c
, typename Algorithms::index_param i
, typename Algorithms::value_param v)
@@ -155,7 +167,14 @@ namespace boost { namespace python { namespace indexing {
else
{
detail::maybe_insert<container_traits::has_insert>
::template apply<Algorithms> (*m_ptr, m_pos, val);
::BOOST_PYTHON_INDEXING_NESTED_TEMPLATE apply
# if defined (BOOST_NO_MEMBER_TEMPLATES) \
&& defined (BOOST_MSVC6_MEMBER_TEMPLATES)
(static_cast<Algorithms *>(0),
# else
<Algorithms> (
# endif
*m_ptr, m_pos, val);
++m_pos; // Advance for any subsequent inserts
}
@@ -165,6 +184,10 @@ namespace boost { namespace python { namespace indexing {
template<bool doit> struct maybe_erase {
template<class Algorithms>
static void apply (
# if defined (BOOST_NO_MEMBER_TEMPLATES) \
&& defined (BOOST_MSVC6_MEMBER_TEMPLATES)
Algorithms *,
# endif
typename Algorithms::container &
, typename Algorithms::index_param
, typename Algorithms::index_param)
@@ -179,6 +202,10 @@ namespace boost { namespace python { namespace indexing {
template<> struct maybe_erase<true> {
template<class Algorithms>
static void apply (
# if defined (BOOST_NO_MEMBER_TEMPLATES) \
&& defined (BOOST_MSVC6_MEMBER_TEMPLATES)
Algorithms *,
# endif
typename Algorithms::container &c
, typename Algorithms::index_param from
, typename Algorithms::index_param to)
@@ -202,9 +229,17 @@ namespace boost { namespace python { namespace indexing {
else
{
detail::maybe_erase<container_traits::has_erase>
::template apply<Algorithms> (*m_ptr, m_pos, m_slice.stop());
::BOOST_PYTHON_INDEXING_NESTED_TEMPLATE apply
# if defined (BOOST_NO_MEMBER_TEMPLATES) \
&& defined (BOOST_MSVC6_MEMBER_TEMPLATES)
(static_cast<Algorithms *>(0),
# else
<Algorithms> (
# endif
*m_ptr, m_pos, m_slice.stop());
}
}
} } }
#endif // BOOST_PYTHON_INDEXING_INT_SLICE_HELPER_HPP

View File

@@ -26,6 +26,7 @@
#include <boost/type_traits.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <boost/python/suite/indexing/container_traits.hpp>
#include <boost/python/suite/indexing/container_suite.hpp>
#include <boost/python/suite/indexing/algorithms.hpp>
#include <boost/python/suite/indexing/algo_selector.hpp>
@@ -34,7 +35,9 @@ namespace boost { namespace python { namespace indexing {
class iterator_range
{
private:
typedef typename boost::call_traits<Iterator>::param_type iterator_param;
typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <Iterator>::param_type
iterator_param;
typedef ::boost::detail::iterator_traits<Iterator> std_traits;
public:
@@ -73,12 +76,26 @@ namespace boost { namespace python { namespace indexing {
iterator m_end;
};
// Array support functions
template<typename T, std::size_t N> T *begin (T (&array)[N]);
template<typename T, std::size_t N> T *end (T (&array)[N]);
// Array support function(s).
template<typename T> iterator_range<T *> make_iterator_range (T *, T*);
#if !BOOST_WORKAROUND (BOOST_MSVC, <= 1200)
template<typename T, std::size_t N> iterator_range<T *> make_iterator_range (
T (&array)[N]);
template<typename T, std::size_t N> T *begin (T (&array)[N]);
template<typename T, std::size_t N> T *end (T (&array)[N]);
# define BOOST_MAKE_ITERATOR_RANGE \
::boost::python::indexing::make_iterator_range
#else
// For compilers that can't deduce template argument array bounds
# define BOOST_MAKE_ITERATOR_RANGE(array) \
::boost::python::indexing::make_iterator_range ( \
(array), ((array) + sizeof(array) / sizeof((array)[0])))
#endif
template<typename Iterator>
iterator_range<Iterator>::iterator_range (
iterator_param begin, iterator_param end)
@@ -141,6 +158,12 @@ namespace boost { namespace python { namespace indexing {
}
}
template<typename T> iterator_range<T *> make_iterator_range (T *p1, T* p2)
{
return iterator_range<T *> (p1, p2);
}
#if !BOOST_WORKAROUND (BOOST_MSVC, <= 1200)
template<typename T, std::size_t N>
T *begin (T (&array)[N]) {
return array;
@@ -155,7 +178,9 @@ namespace boost { namespace python { namespace indexing {
iterator_range<T *> make_iterator_range (T (&array)[N]) {
return iterator_range<T *>(begin (array), end (array));
}
#endif
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
namespace detail {
///////////////////////////////////////////////////////////////////////
// algo_selector support for iterator_range instances
@@ -174,6 +199,13 @@ namespace boost { namespace python { namespace indexing {
typedef default_algorithms<const_traits> const_algorithms;
};
}
#endif
template<class Container, class Traits = base_container_traits<Container> >
struct iterator_range_suite
: container_suite<Container, default_algorithms<Traits> >
{
};
} } }

View File

@@ -23,6 +23,7 @@
#define BOOST_PYTHON_INDEXING_ITERATOR_TRAITS_HPP
#include <boost/python/suite/indexing/suite_utils.hpp>
#include <boost/python/suite/indexing/workaround.hpp>
#include <boost/call_traits.hpp>
#include <boost/type_traits.hpp>
@@ -77,7 +78,14 @@ namespace boost { namespace python { namespace indexing {
};
namespace iterator_detail {
template<typename TraversalTag> struct traits_by_category { };
template<typename TraversalTag> struct traits_by_category {
# if defined(BOOST_MPL_MSVC_60_ETI_BUG)
// MSVC6 needs compilable traits in the unspecialized traits_by_category
template<typename Iter> struct traits {
typedef traits<Iter> type;
};
# endif
};
template<>
struct traits_by_category<std::input_iterator_tag> {
@@ -113,7 +121,7 @@ namespace boost { namespace python { namespace indexing {
template<typename Iterator>
class deduced_traits {
typedef BOOST_DEDUCED_TYPENAME BOOST_ITERATOR_CATEGORY<
typedef BOOST_DEDUCED_TYPENAME ::boost::BOOST_ITERATOR_CATEGORY<
Iterator>::type category;
typedef BOOST_DEDUCED_TYPENAME ::boost::detail::std_category <
@@ -121,7 +129,7 @@ namespace boost { namespace python { namespace indexing {
public:
typedef typename traits_by_category <max_category>
::template traits<Iterator>::type type;
::BOOST_PYTHON_INDEXING_NESTED_TEMPLATE traits<Iterator>::type type;
};
}

View File

@@ -19,6 +19,7 @@
#define BOOST_PYTHON_INDEXING_LIST_HPP
#include <boost/python/suite/indexing/container_traits.hpp>
#include <boost/python/suite/indexing/container_suite.hpp>
#include <boost/python/suite/indexing/algorithms.hpp>
#include <boost/python/suite/indexing/algo_selector.hpp>
#include <list>
@@ -49,6 +50,7 @@ namespace boost { namespace python { namespace indexing {
// static void sort (container &, PyObject *);
};
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
namespace detail {
///////////////////////////////////////////////////////////////////////
// algo_selector support for std::list instances
@@ -67,6 +69,12 @@ namespace boost { namespace python { namespace indexing {
typedef list_algorithms<const_traits> const_algorithms;
};
}
#endif
template<class Container, class Traits = default_sequence_traits<Container> >
struct list_suite : container_suite<Container, list_algorithms<Traits> >
{
};
/////////////////////////////////////////////////////////////////////////
// Reverse the contents of a list (using member function)

View File

@@ -19,8 +19,11 @@
#define BOOST_PYTHON_INDEXING_MAP_HPP
#include <boost/python/suite/indexing/container_traits.hpp>
#include <boost/python/suite/indexing/container_suite.hpp>
#include <boost/python/suite/indexing/algorithms.hpp>
#include <boost/python/suite/indexing/algo_selector.hpp>
#include <boost/python/suite/indexing/algo_selector.hpp>
#include <boost/detail/workaround.hpp>
#include <map>
namespace boost { namespace python { namespace indexing {
@@ -31,14 +34,22 @@ namespace boost { namespace python { namespace indexing {
template<typename Container>
struct map_traits : public default_container_traits<Container>
{
# if BOOST_WORKAROUND (BOOST_MSVC, <= 1200)
// MSVC6 has a nonstandard name for mapped_type in std::map
typedef typename Container::referent_type value_type;
# else
typedef typename Container::mapped_type value_type;
# endif
typedef value_type & reference;
typedef typename Container::key_type index_type; // operator[]
typedef typename Container::key_type key_type; // find, count, ...
typedef typename boost::call_traits<value_type>::param_type value_param;
typedef typename boost::call_traits<key_type>::param_type key_param;
typedef typename boost::call_traits<index_type>::param_type index_param;
typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <value_type>::param_type
value_param;
typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <key_type>::param_type
key_param;
typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <index_type>::param_type
index_param;
BOOST_STATIC_CONSTANT (index_style_t, index_style = index_style_nonlinear);
BOOST_STATIC_CONSTANT (bool, has_find = true);
@@ -77,6 +88,7 @@ namespace boost { namespace python { namespace indexing {
static void insert (container &, index_param, value_param);
};
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
namespace detail {
///////////////////////////////////////////////////////////////////////
// algo_selector support for std::map instances
@@ -112,13 +124,19 @@ namespace boost { namespace python { namespace indexing {
typedef map_algorithms<const_traits> const_algorithms;
};
}
#endif
template<class Container, class Traits = map_traits<Container> >
struct map_suite : container_suite<Container, map_algorithms<Traits> >
{
};
/////////////////////////////////////////////////////////////////////////
// Index into a container (map version)
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits, typename Ovr>
typename map_algorithms<ContainerTraits, Ovr>::reference
BOOST_DEDUCED_TYPENAME map_algorithms<ContainerTraits, Ovr>::reference
map_algorithms<ContainerTraits, Ovr>::get (container &c, index_param ix)
{
return most_derived::find_or_throw (c, ix)->second;
@@ -147,8 +165,8 @@ namespace boost { namespace python { namespace indexing {
container &c, index_param ix, value_param val)
{
typedef std::pair
<typename self_type::container_traits::index_type
, typename self_type::container_traits::value_type>
<BOOST_DEDUCED_TYPENAME self_type::container_traits::index_type
, BOOST_DEDUCED_TYPENAME self_type::container_traits::value_type>
pair_type;
// Can't use std::make_pair, because param types may be references

View File

@@ -18,23 +18,46 @@
#define BOOST_PYTHON_INDEXING_PROXY_ITERATOR_HPP
#include <iterator>
#include <boost/config.hpp>
#include <boost/iterator.hpp>
#include <boost/detail/workaround.hpp>
namespace boost { namespace python { namespace indexing {
template<class ContainerProxy>
template <class ContainerProxy, typename ElementProxy, typename Traits
, typename Size, typename Iter>
class proxy_iterator
: public boost::iterator <
std::random_access_iterator_tag
, ElementProxy
, typename Traits::difference_type
, ElementProxy *
, ElementProxy // Already has reference semantics
>
{
#if !defined (BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template<class C, class H, class G> friend class container_proxy;
#endif
typedef boost::iterator <
std::random_access_iterator_tag
, ElementProxy
, typename Traits::difference_type
, ElementProxy *
, ElementProxy
> base_type;
public:
typedef ContainerProxy container_proxy_;
typedef typename container_proxy_::raw_iterator_traits raw_iterator_traits;
typedef typename raw_iterator_traits::difference_type difference_type;
typedef typename container_proxy_::size_type size_type;
typedef typename container_proxy_::value_type value_type;
typedef typename container_proxy_::raw_iterator raw_iterator;
typedef Iter raw_iterator;
typedef Traits raw_iterator_traits;
typedef Size size_type;
typedef typename base_type::value_type value_type;
typedef typename base_type::difference_type difference_type;
typedef value_type *pointer;
typedef value_type reference; // Already has reference semantics
typedef std::random_access_iterator_tag iterator_category;
typedef value_type reference; // Already has reference semantics
proxy_iterator (container_proxy_ *p, size_type i) : ptr (p), index (i) { }
@@ -90,10 +113,18 @@ namespace boost { namespace python { namespace indexing {
return index < other.index;
}
bool operator<= (proxy_iterator const &other) const {
return index <= other.index;
}
bool operator> (proxy_iterator const &other) const {
return index > other.index;
}
bool operator>= (proxy_iterator const &other) const {
return index >= other.index;
}
void iter_swap (proxy_iterator const &other) const {
ptr->swap_elements (index, other.index);
}
@@ -102,20 +133,28 @@ namespace boost { namespace python { namespace indexing {
// Extensions to the normal iterator interface
// void replace (value_type const &copy) { ptr->replace (index, copy); }
#if defined (BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
// Can't declare container_proxy as friend, so make data public
public:
#else
private:
#endif
container_proxy_ *ptr;
size_type index;
};
} } }
#if !BOOST_WORKAROUND (BOOST_MSVC, == 1300)
// MSVC7.0 can't decide between this and the unspecialized version
namespace std {
template<class C>
template <class C, typename E, typename T, typename S, typename I>
void iter_swap (
boost::python::indexing::proxy_iterator<C> const &first
, boost::python::indexing::proxy_iterator<C> const &second)
boost::python::indexing::proxy_iterator<C, E, T, S, I> const &first
, boost::python::indexing::proxy_iterator<C, E, T, S, I> const &second)
{
first.iter_swap (second);
}
}
#endif
#endif // BOOST_PYTHON_INDEXING_PROXY_ITERATOR_HPP

View File

@@ -19,6 +19,7 @@
#define BOOST_PYTHON_INDEXING_SET_HPP
#include <boost/python/suite/indexing/container_traits.hpp>
#include <boost/python/suite/indexing/container_suite.hpp>
#include <boost/python/suite/indexing/algorithms.hpp>
#include <boost/python/suite/indexing/algo_selector.hpp>
#include <set>
@@ -35,9 +36,12 @@ namespace boost { namespace python { namespace indexing {
typedef typename Container::key_type index_type; // operator[]
typedef typename Container::key_type key_type; // find, count, ...
typedef typename boost::call_traits<value_type>::param_type value_param;
typedef typename boost::call_traits<key_type>::param_type key_param;
typedef typename boost::call_traits<index_type>::param_type index_param;
typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <value_type>::param_type
value_param;
typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <key_type>::param_type
key_param;
typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <index_type>::param_type
index_param;
BOOST_STATIC_CONSTANT (index_style_t, index_style = index_style_nonlinear);
BOOST_STATIC_CONSTANT (bool, has_find = true);
@@ -72,6 +76,7 @@ namespace boost { namespace python { namespace indexing {
static void insert (container &, index_param);
};
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
namespace detail {
///////////////////////////////////////////////////////////////////////
// algo_selector support for std::set instances
@@ -107,6 +112,12 @@ namespace boost { namespace python { namespace indexing {
typedef set_algorithms<const_traits> const_algorithms;
};
}
#endif
template<class Container, class Traits = set_traits<Container> >
struct set_suite : container_suite<Container, set_algorithms<Traits> >
{
};
/////////////////////////////////////////////////////////////////////////
// Insert an element into a set

View File

@@ -46,13 +46,16 @@ namespace boost { namespace python { namespace indexing {
shared_proxy_impl (value_type const &copy);
// Creates value-only (detached) proxy
#if defined (BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
public:
#else
private:
template<class C, class A, class G> friend class container_proxy;
#endif
shared_proxy_impl (ContainerProxy *, size_t);
void detach ();
private:
ContainerProxy *m_owner_ptr; // When attached
size_t m_index; // When attached
std::auto_ptr<value_type> m_element_ptr; // When detached
@@ -85,14 +88,15 @@ namespace boost { namespace python { namespace indexing {
shared_proxy_impl<ContainerProxy>::operator* () const
{
return m_owner_ptr
? m_owner_ptr->raw_container().BOOST_INDEXING_AT (m_index)
? m_owner_ptr->raw_container().BOOST_PYTHON_INDEXING_AT (m_index)
: *m_element_ptr;
}
template<class ContainerProxy>
void shared_proxy_impl<ContainerProxy>::detach ()
{
m_element_ptr.reset (new value_type (**this));
BOOST_PYTHON_INDEXING_RESET_AUTO_PTR (
m_element_ptr, new value_type (**this));
m_owner_ptr = 0;
m_index = static_cast<size_t>(-1);
}

View File

@@ -1,5 +1,3 @@
// -*- mode:c++ -*-
//
// Header file slice.hpp
//
// Copyright (c) 2003 Raoul M. Gough
@@ -29,9 +27,20 @@ namespace boost { namespace python { namespace indexing {
// so that it is possible to register a special converter for
// PySlice_Type and overload C++ functions on slice
slice (slice const &);
#if defined (BOOST_NO_MEMBER_TEMPLATES)
// MSVC6 doesn't seem to be able to invoke the templated
// constructor, so provide explicit overloads to match the
// (currently) known boost::python::object constructors
explicit slice (::boost::python::handle<> const&);
explicit slice (::boost::python::detail::borrowed_reference);
explicit slice (::boost::python::detail::new_reference);
explicit slice (::boost::python::detail::new_non_null_reference);
#else
// Better compilers make life easier
template<typename T> inline slice (T const &ref);
#endif
slice (slice const &); // Copy constructor
};
struct BOOST_PYTHON_DECL integer_slice
@@ -62,6 +71,7 @@ namespace boost { namespace python { namespace indexing {
};
} } }
#if !defined (BOOST_NO_MEMBER_TEMPLATES)
template<typename T>
boost::python::indexing::slice::slice (T const &ref)
: boost::python::object (ref)
@@ -74,6 +84,7 @@ boost::python::indexing::slice::slice (T const &ref)
boost::python::throw_error_already_set();
}
}
#endif
namespace boost { namespace python { namespace converter {
// Specialized converter to handle PySlice_Type objects

View File

@@ -18,6 +18,7 @@
#ifndef BOOST_PYTHON_INDEXING_SLICE_HANDLER_HPP
#define BOOST_PYTHON_INDEXING_SLICE_HANDLER_HPP
#include <boost/python/handle.hpp>
#include <boost/python/object.hpp>
#include <boost/python/list.hpp>
#include <boost/python/extract.hpp>
@@ -46,10 +47,13 @@ namespace boost { namespace python { namespace indexing {
static void set_slice (container &, slice, boost::python::object);
static void del_slice (container &, slice);
static void extend (container &, boost::python::object);
};
namespace detail {
template<typename Policy>
struct postcall_override
{
// This class overrides our Policy's postcall function and
// This class overrides the Policy's postcall function and
// result_conveter to handle the list returned from get_slice.
// The Policy's result_converter is removed, since it gets
// applied within get_slice. Our postcall override applies the
@@ -57,7 +61,7 @@ namespace boost { namespace python { namespace indexing {
// from get_slice.
typedef boost::python::default_result_converter result_converter;
typedef typename Policy::argument_package argument_package; // ?
typedef typename Policy::argument_package argument_package;
postcall_override (Policy const &p);
@@ -67,48 +71,6 @@ namespace boost { namespace python { namespace indexing {
private:
Policy m_base;
};
};
//////////////////////////////////////////////////////////////////////////
// postcall_override constructor
//////////////////////////////////////////////////////////////////////////
template<class Algorithms, class Policy>
slice_handler<Algorithms, Policy>
::postcall_override::postcall_override (Policy const &p)
: m_base (p)
{
}
//////////////////////////////////////////////////////////////////////////
// precall forwarder
//////////////////////////////////////////////////////////////////////////
template<class Algorithms, class Policy>
bool
slice_handler<Algorithms, Policy>
::postcall_override::precall (PyObject *args)
{
return m_base.precall (args);
}
//////////////////////////////////////////////////////////////////////////
// Apply base postcall to each element of the list returend by get_slice
//////////////////////////////////////////////////////////////////////////
template<class Algorithms, class Policy>
PyObject *
slice_handler<Algorithms, Policy>
::postcall_override::postcall (PyObject *args, PyObject *result)
{
int size = PyList_Size (result);
for (int count = 0; count < size; ++count)
{
m_base.postcall (args, PyList_GetItem (result, count));
}
return result;
}
//////////////////////////////////////////////////////////////////////////
@@ -121,7 +83,8 @@ namespace boost { namespace python { namespace indexing {
::make_getitem (Policy const &policy)
{
return
boost::python::make_function (get_slice, postcall_override (policy));
boost::python::make_function (
get_slice, detail::postcall_override<Policy> (policy));
}
//////////////////////////////////////////////////////////////////////////
@@ -163,6 +126,46 @@ namespace boost { namespace python { namespace indexing {
return boost::python::make_function (extend, policy);
}
namespace detail {
////////////////////////////////////////////////////////////////////////
// postcall_override constructor
////////////////////////////////////////////////////////////////////////
template<class Policy>
postcall_override<Policy>::postcall_override (Policy const &p)
: m_base (p)
{
}
////////////////////////////////////////////////////////////////////////
// precall forwarder
////////////////////////////////////////////////////////////////////////
template<class Policy>
bool postcall_override<Policy>::precall (PyObject *args)
{
return m_base.precall (args);
}
////////////////////////////////////////////////////////////////////////
// Apply base postcall to each element of the list returend by get_slice
////////////////////////////////////////////////////////////////////////
template<class Policy>
PyObject *
postcall_override<Policy>::postcall (PyObject *args, PyObject *result)
{
int size = PyList_Size (result);
for (int count = 0; count < size; ++count)
{
m_base.postcall (args, PyList_GetItem (result, count));
}
return result;
}
} // namespace detail
//////////////////////////////////////////////////////////////////////////
// Implementation for the slice version of __getitem__
//////////////////////////////////////////////////////////////////////////
@@ -174,7 +177,9 @@ namespace boost { namespace python { namespace indexing {
{
typedef typename Policy::result_converter converter_type;
typedef typename Algorithms::reference reference;
typename boost::mpl::apply1<converter_type, reference>::type converter;
typename boost::mpl::apply1<converter_type, reference>::type
converter;
boost::python::list result;
@@ -214,11 +219,11 @@ namespace boost { namespace python { namespace indexing {
// a reference to existing object, if possible and sensible) and the
// second allowing implicit conversions.
typedef boost::python::extract<typename Algorithms::value_param>
extractor1;
typedef boost::python::extract <
BOOST_DEDUCED_TYPENAME Algorithms::value_param> extractor1;
typedef boost::python::extract<typename Algorithms::value_type>
extractor2;
typedef boost::python::extract <
BOOST_DEDUCED_TYPENAME Algorithms::value_type> extractor2;
// Note: any error during this operation will probably leave the
// container partially updated. This can occur (for example) if the

View File

@@ -45,7 +45,7 @@ namespace boost { namespace python { namespace indexing {
typedef typename boost::remove_reference<T>::type maybe_const;
public:
static bool const value = ! boost::is_const<maybe_const>::value;
BOOST_STATIC_CONSTANT (bool, value = !boost::is_const<maybe_const>::value);
};
// make_signed attempts to identify the signed version of any

View File

@@ -21,13 +21,15 @@
#ifndef BOOST_PYTHON_INDEXING_VALUE_TRAITS_HPP
#define BOOST_PYTHON_INDEXING_VALUE_TRAITS_HPP
#include <boost/config.hpp>
namespace boost { namespace python { namespace indexing {
template<typename T>
struct value_traits {
static bool const equality_comparable = true;
BOOST_STATIC_CONSTANT (bool, equality_comparable = true);
// Meaning from C++98 standard section 20.1.1
static bool const lessthan_comparable = true;
BOOST_STATIC_CONSTANT (bool, lessthan_comparable = true);
// static bool const has_less = true;
// etc...

View File

@@ -19,11 +19,13 @@
#define BOOST_PYTHON_INDEXING_VECTOR_HPP
#include <boost/python/suite/indexing/container_traits.hpp>
#include <boost/python/suite/indexing/container_suite.hpp>
#include <boost/python/suite/indexing/algorithms.hpp>
#include <boost/python/suite/indexing/algo_selector.hpp>
#include <vector>
namespace boost { namespace python { namespace indexing {
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
namespace detail {
///////////////////////////////////////////////////////////////////////
// algo_selector support for std::vector instances
@@ -42,6 +44,12 @@ namespace boost { namespace python { namespace indexing {
typedef default_algorithms<const_traits> const_algorithms;
};
}
#endif
template<class Container, class Traits = default_sequence_traits<Container> >
struct vector_suite : container_suite<Container, default_algorithms<Traits> >
{
};
} } }

View File

@@ -1,5 +1,3 @@
// -*- mode:c++ -*-
//
// Header file visitor.hpp
//
// Copyright (c) 2003 Raoul M. Gough
@@ -23,6 +21,7 @@
#include <boost/python/def_visitor.hpp>
#include <boost/python/iterator.hpp>
#include <boost/python/default_call_policies.hpp>
#include <boost/type_traits/ice.hpp>
#include <boost/bind.hpp>
#include <functional>
@@ -228,11 +227,12 @@ namespace boost { namespace python { namespace indexing {
static void apply (
PythonClass &pyClass
, Algorithms const &
, Policy const &policy)
, Policy const &)
{
// *FIXME* seperate precall and postcall portions of the
// Should maybe separate precall and postcall portions of the
// policy (precall when generating the range object, postcall
// when returing from range.next())
// when returing from range.next())?
pyClass.def (
"__iter__"
, boost::python::range<Policy> (

View File

@@ -1,5 +1,3 @@
// -*- mode:c++ -*-
//
// Header file workaround.hpp
//
// Indexing-specific workarounds for compiler problems.
@@ -20,14 +18,35 @@
#ifndef BOOST_PYTHON_INDEXING_WORKAROUND_HPP
#define BOOST_PYTHON_INDEXING_WORKAROUND_HPP
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
# if (BOOST_WORKAROUND (__GNUC__, < 3))
# // gcc versions before 3 (like 2.95.3) don't have the "at" member
# // function in std::vector or std::deque
# define BOOST_INDEXING_AT operator[]
# define BOOST_PYTHON_INDEXING_AT operator[]
# else
# define BOOST_INDEXING_AT at
# define BOOST_PYTHON_INDEXING_AT at
# endif
# if BOOST_WORKAROUND (BOOST_MSVC, <= 1300)
// visualc.hpp never seems to define BOOST_NO_MEMBER_TEMPLATE_KEYWORD
// so BOOST_NESTED_TEMPLATE ends up expanding to "template" instead of
// being empty. This causes some compile errors with MSVC[67]
# define BOOST_PYTHON_INDEXING_NESTED_TEMPLATE
// Workaround the lack of a reset member function in std::auto_ptr
namespace boost { namespace python { namespace indexing {
template<typename T> void reset_auto_ptr (T &aptr, T::element_type *pptr) {
aptr = T (pptr);
}
} } }
# define BOOST_PYTHON_INDEXING_RESET_AUTO_PTR \
::boost::python::indexing::reset_auto_ptr
# else
# define BOOST_PYTHON_INDEXING_NESTED_TEMPLATE BOOST_NESTED_TEMPLATE
# define BOOST_PYTHON_INDEXING_RESET_AUTO_PTR( aptr, pptr ) \
(aptr).reset(pptr)
# endif
#endif // BOOST_PYTHON_INDEXING_WORKAROUND_HPP

View File

@@ -16,6 +16,7 @@
//
#include <boost/python/suite/indexing/python_iterator.hpp>
#include <boost/python/suite/indexing/workaround.hpp>
////////////////////////////////////////////////////////////////////////////
// python_iterator factory
@@ -24,11 +25,13 @@
std::auto_ptr<boost::python::indexing::python_iterator>
boost::python::indexing::make_iterator (boost::python::object temp)
{
std::auto_ptr<python_iterator> result;
typedef std::auto_ptr<python_iterator> ptr_type;
ptr_type result;
try
{
result.reset (new python_iter_iterator (temp));
BOOST_PYTHON_INDEXING_RESET_AUTO_PTR (
result, (python_iterator *) new python_iter_iterator (temp));
}
catch (boost::python::error_already_set const &)
@@ -37,7 +40,8 @@ boost::python::indexing::make_iterator (boost::python::object temp)
try
{
result.reset (new python_getitem_iterator (temp));
BOOST_PYTHON_INDEXING_RESET_AUTO_PTR (
result, (python_iterator *) new python_getitem_iterator (temp));
}
catch (boost::python::error_already_set const &)

View File

@@ -1,5 +1,3 @@
// -*- mode:c++ -*-
//
// Module slice.cpp
//
// Copyright (c) 2003 Raoul M. Gough
@@ -18,6 +16,19 @@
#include <boost/python/suite/indexing/slice.hpp>
#include <algorithm>
/////////////////////////////////////////////////////////////////////////////
// MSVC6 workarounds
/////////////////////////////////////////////////////////////////////////////
#if defined (BOOST_NO_MEMBER_TEMPLATES)
namespace boost { namespace python { namespace indexing {
slice::slice (::boost::python::handle<> const &p) : object (p) { }
slice::slice (::boost::python::detail::borrowed_reference p) : object (p) { }
slice::slice (::boost::python::detail::new_reference p) : object (p) { }
slice::slice (::boost::python::detail::new_non_null_reference p) : object (p) { }
} } }
#endif
/////////////////////////////////////////////////////////////////////////////
// slice copy constructor
/////////////////////////////////////////////////////////////////////////////

View File

@@ -23,6 +23,7 @@
#include <sstream>
#include <algorithm>
#include <stdio.h>
#include <boost/type_traits/broken_compiler_spec.hpp>
struct int_wrapper {
static bool our_trace_flag;
@@ -42,6 +43,8 @@ struct int_wrapper {
inline static void setTrace (bool onoff);
};
BOOST_TT_BROKEN_COMPILER_SPEC (int_wrapper)
inline bool operator== (int_wrapper const &lhs, int_wrapper const &rhs);
inline bool operator!= (int_wrapper const &lhs, int_wrapper const &rhs);
inline bool operator< (int_wrapper const &lhs, int_wrapper const &rhs);

View File

@@ -30,7 +30,7 @@ boost::python::indexing::iterator_range<int *> get_array_plain()
{
static int array[] = { 8, 6, 4, 2, 1, 3, 5, 7, 0 };
return boost::python::indexing::make_iterator_range (array);
return BOOST_MAKE_ITERATOR_RANGE (array);
}
boost::python::indexing::iterator_range<int_wrapper *> get_array_wrap()
@@ -40,11 +40,13 @@ boost::python::indexing::iterator_range<int_wrapper *> get_array_wrap()
, int_wrapper(1), int_wrapper(3), int_wrapper(5)
, int_wrapper(7), int_wrapper(0) };
return boost::python::indexing::make_iterator_range (array);
return BOOST_MAKE_ITERATOR_RANGE (array);
}
BOOST_PYTHON_MODULE(test_array_ext)
{
namespace indexing = boost::python::indexing;
boost::python::implicitly_convertible <int, int_wrapper>();
boost::python::def ("setTrace", &int_wrapper::setTrace);
@@ -55,15 +57,23 @@ BOOST_PYTHON_MODULE(test_array_ext)
.def ("__cmp__", compare)
;
typedef boost::python::indexing::iterator_range<int *> Container1;
typedef indexing::iterator_range<int *> Container1;
typedef indexing::iterator_range<int_wrapper *> Container2;
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
typedef indexing::container_suite<Container1> Suite1;
typedef indexing::container_suite<Container2> Suite2;
#else
typedef indexing::iterator_range_suite<Container1> Suite1;
typedef indexing::iterator_range_suite<Container2> Suite2;
#endif
boost::python::class_<Container1>
("Array", boost::python::init<int *, int *>())
.def (boost::python::indexing::container_suite<Container1>());
.def (Suite1());
boost::python::def ("get_array_plain", get_array_plain);
typedef boost::python::indexing::iterator_range<int_wrapper *> Container2;
// reference_existing_object is safe in this case, because the array
// is static, and we never manually destroy any array elements. There
@@ -72,9 +82,9 @@ BOOST_PYTHON_MODULE(test_array_ext)
// lifetimes of the array elements.
boost::python::class_<Container2>
("Array_ref", boost::python::init<int_wrapper *, int_wrapper *>())
.def (boost::python::indexing::container_suite<Container2>
::with_policies(boost::python::return_value_policy
<boost::python::reference_existing_object>()));
.def (Suite2::with_policies (
boost::python::return_value_policy <
boost::python::reference_existing_object>()));
boost::python::def ("get_array_wrap", get_array_wrap);
}

View File

@@ -16,7 +16,9 @@
// $Id$
//
#include <boost/type_traits/broken_compiler_spec.hpp>
#include <boost/python/suite/indexing/container_proxy.hpp>
#include <boost/python/suite/indexing/workaround.hpp>
#include <boost/test/minimal.hpp>
#include <vector>
#include <deque>
@@ -27,6 +29,21 @@
bool int_wrapper::our_trace_flag = true;
unsigned int_wrapper::our_object_counter = 0;
#if !BOOST_WORKAROUND (BOOST_MSVC, <= 1300)
// Works with element_proxy instances because of the reference
// conversion operator
static void increment (int_wrapper &int_wrap, int val) {
int_wrap.increment (val);
}
#else
// The implicit conversion provided by element_proxy doesn't work
// with MSVC[67]. Instead use the element_proxy operator->
template<typename T>
static void increment (T const &proxy, int val) {
proxy->increment (val);
}
#endif
template<typename ProxyContainer>
void initial_tests (ProxyContainer &proxy_container)
{
@@ -60,7 +77,7 @@ void initial_tests (ProxyContainer &proxy_container)
BOOST_CHECK (proxy_container.is_valid());
BOOST_CHECK (ref0.use_count() == 2);
((int_wrapper &) proxy_container[0]).increment (2);
increment (proxy_container[0], 2);
BOOST_CHECK (ref0 == int_wrapper (3));
BOOST_CHECK (proxy_container[0] == int_wrapper (3));
@@ -97,14 +114,15 @@ void test_direct_proxy ()
reference ref0 ((*proxy_auto_p)[0]);
reference refn ((*proxy_auto_p)[proxy_auto_p->size() - 1]);
static_cast<int_wrapper &>(ref0).increment (5);
static_cast<int_wrapper &>(refn).increment (10);
increment (ref0, 5);
increment (refn, 10);
BOOST_CHECK (ref0 == int_wrapper (5));
BOOST_CHECK (refn == int_wrapper (10));
BOOST_CHECK (ref0.use_count() == 2);
BOOST_CHECK (refn.use_count() == 2);
proxy_auto_p.reset(); // Invoke container_proxy destructor
// Invoke container_proxy destructor
BOOST_PYTHON_INDEXING_RESET_AUTO_PTR (proxy_auto_p, 0);
BOOST_CHECK (ref0.use_count() == 1); // Detached
BOOST_CHECK (refn.use_count() == 1); // Detached
@@ -121,8 +139,7 @@ void test_direct_proxy ()
BOOST_CHECK (proxy_container.size() == raw_container.size());
reference ref1 (proxy_container[1]);
static_cast<int_wrapper &>(ref1).increment (5);
increment (ref1, 5);
proxy_container_type temp;
temp.push_back (int_wrapper (10));
reference ref2 (temp[0]);
@@ -163,7 +180,7 @@ void test_indirect_proxy ()
reference ref2 (proxy_container[2]);
BOOST_CHECK (ref2.use_count() == 2); // Still attached
static_cast<int_wrapper &>(proxy_container[2]).increment (5);
increment (proxy_container[2], 5);
BOOST_CHECK (ref2 == int_wrapper (5));
// Notify proxy of insert in raw container (*after* insert)
@@ -171,7 +188,7 @@ void test_indirect_proxy ()
proxy_container.notify_insertion (0, 1);
BOOST_CHECK (proxy_container.is_valid());
BOOST_CHECK (ref2.use_count() == 2); // Still attached
static_cast<int_wrapper &>(proxy_container[3]).increment (5);
increment (proxy_container[3], 5);
BOOST_CHECK (ref2 == int_wrapper (10));
// Create reference to about-to-be-erased value
@@ -186,7 +203,7 @@ void test_indirect_proxy ()
BOOST_CHECK (ref0.use_count() == 1); // Ref to erased value detached
BOOST_CHECK (ref0 == int_wrapper (7)); // Value copied before erase
BOOST_CHECK (ref2.use_count() == 2); // Other ref still attached
static_cast<int_wrapper &>(proxy_container[1]).increment (5);
increment (proxy_container[1], 5);
BOOST_CHECK (ref2 == int_wrapper (15));
// Notify proxy of replacement in raw container (*before* assignment)
@@ -214,6 +231,10 @@ struct deque_generator {
};
};
// Make the indirect holders work with broken compilers
BOOST_TT_BROKEN_COMPILER_SPEC (std::vector<int_wrapper>)
BOOST_TT_BROKEN_COMPILER_SPEC (std::deque<int_wrapper>)
int test_main (int argc, char *argv[])
{
namespace indexing = boost::python::indexing;

View File

@@ -54,24 +54,28 @@ BOOST_PYTHON_MODULE(test_deque_ext)
;
typedef std::deque<int> Container1;
boost::python::class_<Container1>("Deque")
.def (indexing::container_suite<Container1>())
;
typedef std::deque<int_wrapper> Container2;
typedef indexing::container_proxy<
Container2, indexing::identity<Container2>, deque_generator> Container3;
#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
typedef indexing::container_suite<Container1> Suite1;
typedef indexing::container_suite<Container2> Suite2;
typedef indexing::container_suite<Container3> Suite3;
#else
typedef indexing::deque_suite<Container1> Suite1;
typedef indexing::deque_suite<Container2> Suite2;
typedef indexing::container_proxy_suite<Container3> Suite3;
#endif
boost::python::class_<Container1>("Deque").def (Suite1());
// Returning internal references to elements of a deque is
// dangerous - the references can be invalidated by inserts or
// deletes!
boost::python::class_<Container2>("Deque_ref")
.def (indexing::container_suite<Container2>
.def (Suite2
::with_policies (boost::python::return_internal_reference<>()));
typedef indexing::container_proxy<
Container2, indexing::identity<Container2>, deque_generator> Container3;
boost::python::class_<Container3>("Deque_proxy")
.def (indexing::container_suite<Container3>())
;
boost::python::class_<Container3>("Deque_proxy").def (Suite3());
}

View File

@@ -37,12 +37,18 @@ std::vector<int_wrapper> get_vector ()
, int_wrapper(7), int_wrapper(0) };
return std::vector<int_wrapper>
#if BOOST_WORKAROUND (BOOST_MSVC, <=1200)
(array, array + sizeof(array) / sizeof (array[0]));
#else
(boost::python::indexing::begin(array)
, boost::python::indexing::end(array));
#endif
}
BOOST_PYTHON_MODULE(test_indexing_const_ext)
{
namespace indexing = boost::python::indexing;
boost::python::implicitly_convertible <int, int_wrapper>();
boost::python::def ("setTrace", &int_wrapper::setTrace);
@@ -56,8 +62,14 @@ BOOST_PYTHON_MODULE(test_indexing_const_ext)
typedef std::vector<int_wrapper> Container1;
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
typedef indexing::container_suite<Container1 const> Suite1;
#else
typedef indexing::vector_suite<Container1 const> Suite1;
#endif
boost::python::class_<Container1>("Vector_const")
.def (boost::python::indexing::container_suite<Container1 const>())
.def (Suite1())
;
boost::python::def ("get_vector", get_vector);

View File

@@ -29,6 +29,8 @@ unsigned int_wrapper::our_object_counter = 0;
BOOST_PYTHON_MODULE(test_list_ext)
{
namespace indexing = boost::python::indexing;
boost::python::implicitly_convertible <int, int_wrapper>();
boost::python::def ("setTrace", &int_wrapper::setTrace);
@@ -41,6 +43,12 @@ BOOST_PYTHON_MODULE(test_list_ext)
typedef std::list<int_wrapper> Container1;
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
typedef indexing::container_suite<Container1> Suite1;
#else
typedef indexing::list_suite<Container1> Suite1;
#endif
boost::python::class_<Container1>("List")
.def (boost::python::indexing::container_suite<Container1>());
.def (Suite1());
}

View File

@@ -33,6 +33,8 @@ unsigned int_wrapper::our_object_counter = 0;
BOOST_PYTHON_MODULE(test_vector_ext)
{
namespace indexing = boost::python::indexing;
boost::python::implicitly_convertible <int, int_wrapper>();
boost::python::def ("setTrace", &int_wrapper::setTrace);
@@ -44,40 +46,33 @@ BOOST_PYTHON_MODULE(test_vector_ext)
;
typedef std::vector<int> Container1;
typedef std::vector<int_wrapper> Container2;
typedef indexing::container_proxy< std::vector<int_wrapper> > Container3;
#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
typedef indexing::container_suite<Container1> Suite1;
typedef indexing::container_suite<Container2> Suite2;
typedef indexing::container_suite<Container3> Suite3;
#else
typedef indexing::vector_suite<Container1> Suite1;
typedef indexing::vector_suite<Container2> Suite2;
typedef indexing::container_proxy_suite<Container3> Suite3;
#endif
boost::python::class_<Container1>("Vector")
.def (boost::python::indexing::container_suite<Container1>())
.def (Suite1())
.def ("reserve", &Container1::reserve)
;
typedef std::vector<int_wrapper> Container2;
// Returning internal references to elements of a vector is
// dangerous - the references can be invalidated by inserts or
// deletes!
boost::python::class_<Container2>("Vector_ref")
.def (boost::python::indexing::container_suite<Container2>
.def (Suite2
::with_policies (boost::python::return_internal_reference<>()));
typedef boost::python::indexing::container_proxy< std::vector<int_wrapper> >
Container3;
boost::python::class_<Container3>("Vector_proxy")
.def (boost::python::indexing::container_suite<Container3>())
.def (Suite3())
.def ("reserve", &Container3::reserve)
;
/* The no-partial-specialization version for vector<int>
using namespace boost::python;
using namespace indexing;
class_<std::vector<int> > ("vector_int")
.def (visitor <
default_algorithms <
default_sequence_traits <
std::vector <int> > >,
return_value_policy <return_by_value>
>());
*/
}

View File

@@ -15,13 +15,19 @@
#include "int_wrapper.hpp"
#include <boost/shared_ptr.hpp>
#include <boost/type_traits/broken_compiler_spec.hpp>
typedef boost::shared_ptr<int_wrapper> int_wrapper_holder;
#if !BOOST_WORKAROUND (BOOST_MSVC, == 1200)
// Declare overloads for correct sort and find of int_wrappers via
// shared pointers
typedef boost::shared_ptr<int_wrapper> int_wrapper_holder;
bool operator< (int_wrapper_holder const &, int_wrapper_holder const &);
bool operator== (int_wrapper_holder const &, int_wrapper_holder const &);
bool operator!= (int_wrapper_holder const &, int_wrapper_holder const &);
#endif
BOOST_TT_BROKEN_COMPILER_SPEC (boost::shared_ptr<int_wrapper>)
#include <boost/python/suite/indexing/container_suite.hpp>
#include <boost/python/suite/indexing/vector.hpp>
@@ -35,6 +41,7 @@ bool operator!= (int_wrapper_holder const &, int_wrapper_holder const &);
bool int_wrapper::our_trace_flag = true;
unsigned int_wrapper::our_object_counter = 0;
#if !BOOST_WORKAROUND (BOOST_MSVC, == 1200)
bool operator< (int_wrapper_holder const &lhs, int_wrapper_holder const &rhs)
{
return (*lhs) < (*rhs);
@@ -49,6 +56,56 @@ bool operator!= (int_wrapper_holder const &lhs, int_wrapper_holder const &rhs)
{
return (*lhs) != (*rhs);
}
#endif
namespace indexing = boost::python::indexing;
typedef std::vector<int_wrapper_holder> Container1;
#if BOOST_WORKAROUND (BOOST_MSVC, == 1200)
// Unfortunately, the comparison operator overloads don't work under
// MSVC6, so we have to use a sledgehammer and replace the
// implementations of some of the search functions
struct bound_compare {
int_wrapper_holder m_lhs;
bound_compare (int_wrapper_holder const &lhs) : m_lhs (lhs) { }
bool operator()(int_wrapper_holder const &rhs) { return (*m_lhs) == (*rhs); }
};
struct msvc6_vector_shared_algorithms
: public indexing::default_algorithms <
indexing::default_sequence_traits<Container1>
, msvc6_vector_shared_algorithms
>
{
typedef indexing::default_algorithms <
indexing::default_sequence_traits<Container1>
, msvc6_vector_shared_algorithms
> base_type;
typedef msvc6_vector_shared_algorithms self_type;
// key_param will be boost::shared_ptr<int_wrapper> or ref to same
static bool less_than (key_param lhs, key_param rhs) {
return (*lhs) < (*rhs);
}
static iterator find (container &c, key_param k) {
return std::find_if (c.begin(), c.end(), bound_compare (k));
}
static size_type count (container &c, key_param k) {
return std::count_if (c.begin(), c.end(), bound_compare (k));
}
static void sort (container &c) {
std::sort (c.begin(), c.end(), self_type::less_than);
}
};
#endif
BOOST_PYTHON_MODULE(test_vector_shared_ext)
{
@@ -63,10 +120,22 @@ BOOST_PYTHON_MODULE(test_vector_shared_ext)
.def ("__cmp__", compare)
;
typedef std::vector<int_wrapper_holder> Container1;
#if BOOST_WORKAROUND (BOOST_MSVC, == 1200)
// MSVC6 version here
typedef indexing::container_suite <
Container1, msvc6_vector_shared_algorithms> Suite1;
#elif !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
// Normal version here
typedef indexing::container_suite<Container1> Suite1;
#else
// For any other compilers that don't have partial specialization
typedef indexing::vector_suite<Container1> Suite1;
#endif
boost::python::class_<Container1>("Vector_shared")
.def (boost::python::indexing::container_suite<Container1>())
.def (Suite1())
.def ("reserve", &Container1::reserve)
;
}

View File

@@ -30,6 +30,8 @@ unsigned int_wrapper::our_object_counter = 0;
BOOST_PYTHON_MODULE(testnonlinear)
{
namespace indexing = boost::python::indexing;
boost::python::implicitly_convertible <int, int_wrapper>();
boost::python::def ("setTrace", &int_wrapper::setTrace);
@@ -43,21 +45,12 @@ BOOST_PYTHON_MODULE(testnonlinear)
typedef std::map<std::string, int_wrapper> Container1;
typedef std::set<std::string> Container2;
#if !BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
typedef boost::python::indexing::container_suite<Container1> Suite1;
typedef boost::python::indexing::container_suite<Container2> Suite2;
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
typedef indexing::container_suite<Container1> Suite1;
typedef indexing::container_suite<Container2> Suite2;
#else
typedef boost::python::indexing::container_suite
<Container1
, boost::python::indexing::map_algorithms
<boost::python::indexing::map_traits
<Container1> > > Suite1;
typedef boost::python::indexing::container_suite
<Container2
, boost::python::indexing::set_algorithms
<boost::python::indexing::set_traits
<Container2> > > Suite2;
typedef indexing::map_suite<Container1> Suite1;
typedef indexing::set_suite<Container2> Suite2;
#endif
boost::python::class_<Container1>("Map").def (Suite1());