2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-22 17:32:55 +00:00

Add optional override parameter to all algorithm templates

[SVN r20378]
This commit is contained in:
Raoul Gough
2003-10-14 12:48:35 +00:00
parent 278bb1a861
commit fbf82cc6e9

View File

@@ -26,16 +26,37 @@
#include <boost/python/errors.hpp>
#include <boost/python/suite/indexing/int_slice_helper.hpp>
#include <boost/python/suite/indexing/slice.hpp>
#include <boost/mpl/if.hpp>
#include <algorithm>
#include <stdexcept>
#include <limits>
#include <string>
namespace boost { namespace python { namespace indexing {
template<typename ContainerTraits>
struct default_algorithms
namespace detail {
struct no_override { };
template<typename Base, typename Override>
struct maybe_override
{
// Probably need to disable this if there is no partial
// specialization support, because Override is almost certain to
// be an incomplete type. If that is right, the workaround
// version would just have to do "typedef Base type;"
typedef typename mpl::if_
<is_same <Override, no_override>, Base, Override>
::type type;
};
}
template<typename ContainerTraits, typename Ovr = detail::no_override>
class default_algorithms
{
typedef default_algorithms<ContainerTraits> self_type;
typedef default_algorithms<ContainerTraits, Ovr> self_type;
typedef typename detail::maybe_override<self_type, Ovr>::type most_derived;
public:
typedef ContainerTraits container_traits;
// Import typedefs from the container_traits for convenience
@@ -91,11 +112,17 @@ namespace boost { namespace python { namespace indexing {
// Special cases for std::list
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
struct list_algorithms : public default_algorithms<ContainerTraits>
template<typename ContainerTraits, typename Ovr = detail::no_override>
class list_algorithms
: public default_algorithms
<ContainerTraits
, typename detail::maybe_override
<list_algorithms<ContainerTraits, Ovr>, Ovr>
::type>
{
private:
typedef default_algorithms<ContainerTraits> Parent;
typedef list_algorithms<ContainerTraits, Ovr> self_type;
typedef typename detail::maybe_override<self_type, Ovr>::type most_derived;
typedef default_algorithms<ContainerTraits, most_derived> Parent;
public:
typedef typename Parent::container container;
@@ -110,12 +137,17 @@ namespace boost { namespace python { namespace indexing {
// Base class for associative containers
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
struct assoc_algorithms : public default_algorithms<ContainerTraits>
template<typename ContainerTraits, typename Ovr = detail::no_override>
class assoc_algorithms
: public default_algorithms
<ContainerTraits
, typename detail::maybe_override
<assoc_algorithms<ContainerTraits, Ovr>, Ovr>
::type>
{
private:
typedef default_algorithms<ContainerTraits> Parent;
typedef assoc_algorithms<ContainerTraits> self_type;
typedef assoc_algorithms<ContainerTraits, Ovr> self_type;
typedef typename detail::maybe_override<self_type, Ovr>::type most_derived;
typedef default_algorithms<ContainerTraits, most_derived> Parent;
public:
typedef typename Parent::iterator iterator;
@@ -142,12 +174,17 @@ namespace boost { namespace python { namespace indexing {
// Special case for sets
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
struct set_algorithms : public assoc_algorithms<ContainerTraits>
template<typename ContainerTraits, typename Ovr = detail::no_override>
class set_algorithms
: public assoc_algorithms
<ContainerTraits
, typename detail::maybe_override
<set_algorithms<ContainerTraits, Ovr>, Ovr>
::type>
{
private:
typedef assoc_algorithms<ContainerTraits> Parent;
typedef set_algorithms<ContainerTraits> self_type;
typedef set_algorithms<ContainerTraits, Ovr> self_type;
typedef typename detail::maybe_override<self_type, Ovr>::type most_derived;
typedef assoc_algorithms<ContainerTraits, most_derived> Parent;
public:
typedef typename Parent::container container;
@@ -162,12 +199,17 @@ namespace boost { namespace python { namespace indexing {
// Special case for map
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
struct map_algorithms : public assoc_algorithms<ContainerTraits>
template<typename ContainerTraits, typename Ovr = detail::no_override>
class map_algorithms
: public assoc_algorithms
<ContainerTraits
, typename detail::maybe_override
<map_algorithms<ContainerTraits, Ovr>, Ovr>
::type>
{
private:
typedef assoc_algorithms<ContainerTraits> Parent;
typedef map_algorithms<ContainerTraits> self_type;
typedef map_algorithms<ContainerTraits, Ovr> self_type;
typedef typename detail::maybe_override<self_type, Ovr>::type most_derived;
typedef assoc_algorithms<ContainerTraits, most_derived> Parent;
public:
typedef typename Parent::container container;
@@ -186,9 +228,9 @@ namespace boost { namespace python { namespace indexing {
// Get the size of a container
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
typename default_algorithms<ContainerTraits>::size_type
default_algorithms<ContainerTraits>::size (container &c)
template<typename ContainerTraits, typename Ovr>
typename default_algorithms<ContainerTraits, Ovr>::size_type
default_algorithms<ContainerTraits, Ovr>::size (container &c)
{
return c.size();
}
@@ -197,15 +239,15 @@ namespace boost { namespace python { namespace indexing {
// Range check an index and throw out_of_range if necessary
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
typename default_algorithms<ContainerTraits>::size_type
default_algorithms<ContainerTraits>::bounds_check (container &c
, index_param ix
, char const *msg
, bool one_past
, bool truncate)
template<typename ContainerTraits, typename Ovr>
typename default_algorithms<ContainerTraits, Ovr>::size_type
default_algorithms<ContainerTraits, Ovr>::bounds_check (container &c
, index_param ix
, char const *msg
, bool one_past
, bool truncate)
{
size_type bound = size(c) + (one_past ? 1 : 0);
size_type bound = most_derived::size(c) + (one_past ? 1 : 0);
size_type result;
if (truncate)
@@ -253,26 +295,26 @@ namespace boost { namespace python { namespace indexing {
// Find an element in a container (std algorithm version)
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
typename default_algorithms<ContainerTraits>::iterator
default_algorithms<ContainerTraits>::find (container &c
, key_param key)
template<typename ContainerTraits, typename Ovr>
typename default_algorithms<ContainerTraits, Ovr>::iterator
default_algorithms<ContainerTraits, Ovr>::find (container &c
, key_param key)
{
return std::find (begin(c), end(c), key);
return std::find (most_derived::begin(c), most_derived::end(c), key);
}
/////////////////////////////////////////////////////////////////////////
// Find an element and return its index (std algorithm version)
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
typename default_algorithms<ContainerTraits>::size_type
default_algorithms<ContainerTraits>::get_index (container &c
, key_param key)
template<typename ContainerTraits, typename Ovr>
typename default_algorithms<ContainerTraits, Ovr>::size_type
default_algorithms<ContainerTraits, Ovr>::get_index (container &c
, key_param key)
{
iterator temp (find (c, key));
iterator temp (most_derived::find (c, key));
if (temp == end(c))
if (temp == most_derived::end(c))
{
PyErr_SetString (PyExc_ValueError
, "get_index: element not found");
@@ -280,66 +322,66 @@ namespace boost { namespace python { namespace indexing {
boost::python::throw_error_already_set ();
}
return std::distance (begin (c), temp);
return std::distance (most_derived::begin (c), temp);
}
/////////////////////////////////////////////////////////////////////////
// Count occurances of an element in a container (std algorithm version)
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
typename default_algorithms<ContainerTraits>::size_type
default_algorithms<ContainerTraits>::count (container &c
, key_param key)
template<typename ContainerTraits, typename Ovr>
typename default_algorithms<ContainerTraits, Ovr>::size_type
default_algorithms<ContainerTraits, Ovr>::count (container &c
, key_param key)
{
return std::count (begin(c), end(c), key);
return std::count (most_derived::begin(c), most_derived::end(c), key);
}
/////////////////////////////////////////////////////////////////////////
// Check whether a container contains the given element (std algo ver)
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
template<typename ContainerTraits, typename Ovr>
bool
default_algorithms<ContainerTraits>::contains (container &c
, key_param key)
default_algorithms<ContainerTraits, Ovr>::contains (container &c
, key_param key)
{
return find (c, key) != end(c);
return most_derived::find (c, key) != most_derived::end(c);
}
/////////////////////////////////////////////////////////////////////////
// Index into a container (generic version)
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
typename default_algorithms<ContainerTraits>::reference
default_algorithms<ContainerTraits>::get (container &c
, index_param ix)
template<typename ContainerTraits, typename Ovr>
typename default_algorithms<ContainerTraits, Ovr>::reference
default_algorithms<ContainerTraits, Ovr>::get (container &c
, index_param ix)
{
return c[bounds_check (c, ix, "get")];
return c[most_derived::bounds_check (c, ix, "get")];
}
/////////////////////////////////////////////////////////////////////////
// Assign a value at a particular index (generic version)
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
template<typename ContainerTraits, typename Ovr>
void
default_algorithms<ContainerTraits>::assign (container &c
, index_param ix
, value_param val)
default_algorithms<ContainerTraits, Ovr>::assign (container &c
, index_param ix
, value_param val)
{
c[bounds_check (c, ix, "assign")] = val;
c[most_derived::bounds_check (c, ix, "assign")] = val;
}
/////////////////////////////////////////////////////////////////////////
// Insert at end of a container (generic version)
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
template<typename ContainerTraits, typename Ovr>
void
default_algorithms<ContainerTraits>::push_back (container &c
, value_param v)
default_algorithms<ContainerTraits, Ovr>::push_back (container &c
, value_param v)
{
c.push_back (v);
}
@@ -348,16 +390,18 @@ namespace boost { namespace python { namespace indexing {
// Insert at an index in the container (generic version)
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
template<typename ContainerTraits, typename Ovr>
void
default_algorithms<ContainerTraits>::insert (container &c
, index_param i
, value_param v)
default_algorithms<ContainerTraits, Ovr>::insert (container &c
, index_param i
, value_param v)
{
iterator insert_pos (c.begin());
iterator insert_pos (most_derived::begin(c));
// Index may range up to c.size() inclusive to allow inserting at end
std::advance (insert_pos, bounds_check (c, i, "insert", true, true));
std::advance (insert_pos
, most_derived::bounds_check (c, i, "insert", true, true));
c.insert (insert_pos, v);
}
@@ -365,70 +409,80 @@ namespace boost { namespace python { namespace indexing {
// Erase between given indexes in the container (generic version)
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
template<typename ContainerTraits, typename Ovr>
void
default_algorithms<ContainerTraits>::erase_range (container &c
, index_param from
, index_param to)
default_algorithms<ContainerTraits, Ovr>::erase_range (container &c
, index_param from
, index_param to)
{
// End index is one-past-the-end, so may range up to c.size() inclusive
iterator start (most_derived::begin(c));
iterator finish (most_derived::begin(c));
c.erase (c.begin() + bounds_check (c, from, "erase_range (from)")
, c.begin() + bounds_check (c, to, "erase_range (to)", true));
// Start index must be properly in bounds
std::advance
(start, most_derived::bounds_check (c, from, "erase_range (from)"));
// End index is one-past-the-end, so may range up to c.size() inclusive
std::advance
(finish, most_derived::bounds_check (c, to, "erase_range (to)", true));
c.erase (start, finish);
}
/////////////////////////////////////////////////////////////////////////
// Erase one element at the given index in the container (generic version)
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
template<typename ContainerTraits, typename Ovr>
void
default_algorithms<ContainerTraits>::erase_one (container &c
, index_param ix)
default_algorithms<ContainerTraits, Ovr>::erase_one (container &c
, index_param ix)
{
c.erase (c.begin() + bounds_check (c, ix, "erase_one"));
iterator iter (most_derived::begin(c));
std::advance (iter, most_derived::bounds_check (c, ix, "erase_one"));
c.erase (iter);
}
/////////////////////////////////////////////////////////////////////////
// Reverse the contents of a container (std algorithm version)
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
void default_algorithms<ContainerTraits>::reverse (container &c)
template<typename ContainerTraits, typename Ovr>
void default_algorithms<ContainerTraits, Ovr>::reverse (container &c)
{
std::reverse (begin(c), end(c));
std::reverse (most_derived::begin(c), most_derived::end(c));
}
/////////////////////////////////////////////////////////////////////////
// Sort the contents of a container (std algorithm version)
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
void default_algorithms<ContainerTraits>::sort (container &c)
template<typename ContainerTraits, typename Ovr>
void default_algorithms<ContainerTraits, Ovr>::sort (container &c)
{
std::sort (begin(c), end(c));
std::sort (most_derived::begin(c), most_derived::end(c));
}
/////////////////////////////////////////////////////////////////////////
// slice_helper factory function (default version)
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
typename default_algorithms<ContainerTraits>::slice_helper
default_algorithms<ContainerTraits>
template<typename ContainerTraits, typename Ovr>
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, size (c)));
return slice_helper (c, integer_slice (sl, most_derived::size (c)));
}
/////////////////////////////////////////////////////////////////////////
// Visitor helper function (default version)
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
template<typename ContainerTraits, typename Ovr>
template<typename PythonClass, typename Policy>
void
default_algorithms<ContainerTraits>
default_algorithms<ContainerTraits, Ovr>
::visitor_helper (PythonClass &pyClass, Policy const &policy)
{
container_traits::visitor_helper (pyClass, policy);
@@ -438,8 +492,8 @@ namespace boost { namespace python { namespace indexing {
// Reverse the contents of a list (member function version)
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
void list_algorithms<ContainerTraits>::reverse (container &c)
template<typename ContainerTraits, typename Ovr>
void list_algorithms<ContainerTraits, Ovr>::reverse (container &c)
{
c.reverse();
}
@@ -448,8 +502,8 @@ namespace boost { namespace python { namespace indexing {
// Sort the contents of a container (std algorithm version)
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
void list_algorithms<ContainerTraits>::sort (container &c)
template<typename ContainerTraits, typename Ovr>
void list_algorithms<ContainerTraits, Ovr>::sort (container &c)
{
c.sort();
}
@@ -458,32 +512,32 @@ namespace boost { namespace python { namespace indexing {
// Index into a container (associative version)
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
typename assoc_algorithms<ContainerTraits>::reference
assoc_algorithms<ContainerTraits>::get (container &c, index_param ix)
template<typename ContainerTraits, typename Ovr>
typename assoc_algorithms<ContainerTraits, Ovr>::reference
assoc_algorithms<ContainerTraits, Ovr>::get (container &c, index_param ix)
{
return *find_or_throw (c, ix);
return *most_derived::find_or_throw (c, ix);
}
/////////////////////////////////////////////////////////////////////////
// Index into a container (map version)
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
typename map_algorithms<ContainerTraits>::reference
map_algorithms<ContainerTraits>::get (container &c, index_param ix)
template<typename ContainerTraits, typename Ovr>
typename map_algorithms<ContainerTraits, Ovr>::reference
map_algorithms<ContainerTraits, Ovr>::get (container &c, index_param ix)
{
return self_type::find_or_throw (c, ix)->second;
return most_derived::find_or_throw (c, ix)->second;
}
/////////////////////////////////////////////////////////////////////////
// Erase elements with the given key (associative version)
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
template<typename ContainerTraits, typename Ovr>
void
assoc_algorithms<ContainerTraits>::erase_one (container &c
, key_param key)
assoc_algorithms<ContainerTraits, Ovr>::erase_one (container &c
, key_param key)
{
if (c.erase (key) == 0)
{
@@ -495,26 +549,26 @@ namespace boost { namespace python { namespace indexing {
}
/////////////////////////////////////////////////////////////////////////
// Assign a value at a particular index (set version)
// Assign a value at a particular index (set version with dummy param)
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
template<typename ContainerTraits, typename Ovr>
void
set_algorithms<ContainerTraits>::assign (container &c
, index_param ix
, value_param val)
set_algorithms<ContainerTraits, Ovr>::assign (container &c
, index_param ix
, value_param dummy)
{
insert (c, ix); // Ignore dummy value parameter
most_derived::insert (c, ix); // Ignore dummy value parameter
}
/////////////////////////////////////////////////////////////////////////
// Insert an element into a set
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
template<typename ContainerTraits, typename Ovr>
void
set_algorithms<ContainerTraits>::insert (container &c
, index_param ix)
set_algorithms<ContainerTraits, Ovr>::insert (container &c
, index_param ix)
{
if (!c.insert (ix).second)
{
@@ -529,11 +583,11 @@ namespace boost { namespace python { namespace indexing {
// Assign a value at a particular index (map version)
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
template<typename ContainerTraits, typename Ovr>
void
map_algorithms<ContainerTraits>::assign (container &c
, index_param ix
, value_param val)
map_algorithms<ContainerTraits, Ovr>::assign (container &c
, index_param ix
, value_param val)
{
c[ix] = val; // Handles overwrite and insert
}
@@ -542,11 +596,11 @@ namespace boost { namespace python { namespace indexing {
// Insert a new key, value pair into a map
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
template<typename ContainerTraits, typename Ovr>
void
map_algorithms<ContainerTraits>::insert (container &c
, index_param ix
, value_param val)
map_algorithms<ContainerTraits, Ovr>::insert (container &c
, index_param ix
, value_param val)
{
typedef std::pair
<typename self_type::container_traits::index_type
@@ -568,9 +622,10 @@ namespace boost { namespace python { namespace indexing {
// Find an element in an associative container
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
typename assoc_algorithms<ContainerTraits>::iterator
assoc_algorithms<ContainerTraits>::find (container &c, key_param key)
template<typename ContainerTraits, typename Ovr>
typename assoc_algorithms<ContainerTraits, Ovr>::iterator
assoc_algorithms<ContainerTraits, Ovr>
::find (container &c, key_param key)
{
return c.find (key);
}
@@ -579,12 +634,12 @@ namespace boost { namespace python { namespace indexing {
// Find an element in an associative container
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
template<typename ContainerTraits, typename Ovr>
bool
assoc_algorithms<ContainerTraits>::contains (container &c
, key_param key)
assoc_algorithms<ContainerTraits, Ovr>::contains (container &c
, key_param key)
{
return self_type::find (c, key) != self_type::end(c);
return most_derived::find (c, key) != most_derived::end(c);
}
/////////////////////////////////////////////////////////////////////////
@@ -592,14 +647,14 @@ namespace boost { namespace python { namespace indexing {
// not found
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
typename assoc_algorithms<ContainerTraits>::iterator
assoc_algorithms<ContainerTraits>::find_or_throw (container &c
, index_param ix)
template<typename ContainerTraits, typename Ovr>
typename assoc_algorithms<ContainerTraits, Ovr>::iterator
assoc_algorithms<ContainerTraits, Ovr>::find_or_throw (container &c
, index_param ix)
{
iterator iter = self_type::find (c, ix);
iterator iter = most_derived::find (c, ix);
if (iter == self_type::end(c))
if (iter == most_derived::end(c))
{
PyErr_SetString (PyExc_ValueError
, "associative container: key not found");
@@ -614,10 +669,10 @@ namespace boost { namespace python { namespace indexing {
// Count occurances of an element in a container (associative version)
/////////////////////////////////////////////////////////////////////////
template<typename ContainerTraits>
typename assoc_algorithms<ContainerTraits>::size_type
assoc_algorithms<ContainerTraits>::count (container &c
, key_param key)
template<typename ContainerTraits, typename Ovr>
typename assoc_algorithms<ContainerTraits, Ovr>::size_type
assoc_algorithms<ContainerTraits, Ovr>::count (container &c
, key_param key)
{
return c.count (key);
}