diff --git a/doc/v2/indexing.html b/doc/v2/indexing.html new file mode 100644 index 00000000..444044c8 --- /dev/null +++ b/doc/v2/indexing.html @@ -0,0 +1,278 @@ + + +
+ Indexing is a Python module for easy exportation of indexable C++ containers + to Python. Indexable containers are containers that allow random access through + the operator[] (e.g. std::vector). +
While Boost Python has all the facilities to expose indexable C++ containers + such as the ubiquitous std::vector to Python, the procedure is not as straightforward + as we'd like it to be. When in Python, do as the Pythonians do. Yet, Python + containers do not map easily to C++ containers. Emulating Python containers + in C++ (see Python Reference Manual, Emulating + container types) using Boost Python is non trivial. There are a lot of + issues to consider before we can map a C++ container to Python which involves + implementing wrapper functions for the methods __len__, __getitem__, + __setitem__, __delitem__, __iter__ + and __contains. +
The goals:
The indexing_suite class is the base protocol class for the management + of C++ containers intended to be integrated to Python. The objective is make + a C++ container look and feel and behave exactly as we'd expect a Python container. + The class automatically wraps these special Python methods:
+The indexing_suite is not meant to be used as is. A couple of policy + functions must be supplied by subclasses of indexing_suite. However, + a set of indexing_suite subclasses for the standard indexable STL containers + will be provided, In most cases, we can simply use the available predefined + suites. In some cases, if needed, we can refine them to suit our needs.
+The vector_indexing_suite class is a predefined indexing_suite + derived class for wrapping std::vector (and std::vector like) + classes (currently, this is the only predefined suite available). It provides + all the policies required by the indexing_suite.
+Example usage:
+ class X {...};
+ ...
+
+ class_<std::vector<X> >("XVec")
+ .def(vector_indexing_suite<std::vector<X> >())
+ ;
+
+That's it! XVec is now a full-fledged Python container (see the example + in full, along with its python + test).
+template <+
class Container
, class DerivedPolicies
, bool NoProxy = false
, class Element = typename Container::value_type
, class Key = typename Container::value_type
, class Index = typename Container::size_type
>
class indexing_suite
: public def_arg<
indexing_suite<
Container
, DerivedPolicies
, NoProxy
, Element
, Key
, Index
> >
{
public:
template <class Class>+
void visit(Class& cl) const;
};
static element_type&+
get_item(Container& container, index_type i); + + static object
get_slice(Container& container, index_type from, index_type to); + + static void
set_item(Container& container, index_type i, element_type const& v); + + static void
set_slice(
Container& container, index_type from,
index_type to, element_type const& v
); + + template <class Iter>
static void
set_slice(Container& container, index_type from,
index_type to, Iter first, Iter last
); + + static void
delete_item(Container& container, index_type i); + + static void
delete_slice(Container& container, index_type from, index_type to); + + static size_t
size(Container& container); + + template <class T>
static bool
contains(Container& container, T const& val); + + static index_type
convert_index(Container& container, PyObject* i); + + static index_type
adjust_index(index_type current, index_type from,
index_type to, size_type len
); +
++Most of these policies are self explanatory. convert_index + and adjust_index, however, deserves some explanation.
+convert_index converts an Python index into a C++ + index that the container can handle. For instance, negative indexes in Python, + by convention, indexes from the right (e.g. C[-1] indexes the rightmost + element in C). convert_index should handle + the necessary conversion for the C++ container (e.g. convert -1 to + C.size()-1). convert_index should also + be able to convert the type of the index (A dynamic Python type) to the actual + type that the C++ container expects.
+When a container expands or contracts, held indexes to its elements must + be adjusted to follow the movement of data. For instance, if we erase 3 elements, + starting from index 0 from a 5 element vector, what used to be at index 4 + will now be at index 1:
++ [a][b][c][d][e] ---> [d][e] + ^ ^ + 4 1+adjust_index takes care of the adjustment. Given + a current index, the function should return the adjusted index when data in + the container at index from..to is replaced by len + elements.
+
def_arg+The Boost Python class_ interface provides + a generic visitation interface to avoid cluttering the class interface + through the def_arg mechanism. indexing_suite + derives from the def_arg base class and provides the requisite + visit member function taking in a const reference + to the class. |
+
+ template <+
class Container,
bool NoProxy = false,
class DerivedPolicies = unspecified_default
class vector_indexing_suite
: public indexing_suite<Container, DerivedPolicies, NoProxy>
{
public:
typedef typename Container::value_type element_type;
typedef typename Container::value_type key_type;
typedef typename Container::size_type index_type;
typedef typename Container::size_type size_type;
typedef typename Container::difference_type difference_type;
static element_type&
get_item(Container& container, index_type i); + + static object + get_slice(Container& container, index_type from, index_type to); + + static void
set_item(Container& container, index_type i, element_type const& v); + + static void + set_slice(Container& container, index_type from, + index_type to, element_type const& v); + + template <class Iter>
static void
set_slice(Container& container, index_type from,
index_type to, Iter first, Iter last); + + static void + delete_item(Container& container, index_type i); + + static void + delete_slice(Container& container, index_type from, index_type to);
+ static size_t + size(Container& container); + + static bool + contains(Container& container, key_type const& key); + + static index_type + convert_index(Container& container, PyObject* i); + + static index_type + adjust_index(index_type current, index_type from, + index_type to, size_type len); + };