diff --git a/doc/v2/containers.html b/doc/v2/containers.html index f1c3927b..a687fafd 100755 --- a/doc/v2/containers.html +++ b/doc/v2/containers.html @@ -49,6 +49,9 @@
container_suite.hpp
+
+ Container-specific headers +
Using policies
@@ -166,18 +169,27 @@

- The main iterface to the library is via an object which adds a - number of Python functions to a class via a single - def call. The selection of what Python functions to - add happens transparently for instances of the standard - container templates [1], so that code like - the following should compile and "just work". + The main iterface to the library is via the templated class + container_suite, an object of which adds a number + of Python functions to an extension class via a single + def call. Support is provided for all of the + standard container templates [1] via + container-specific header files, as shown in the following + example:

+#include <boost/python/suite/indexing/container_suite.hpp>
+#include <boost/python/suite/indexing/vector.hpp>
+#include <boost/python/class.hpp>
+#include <boost/python/module.hpp>
+#include <vector>
+
+BOOST_PYTHON_MODULE(example) {
   class_< std::vector<int> > ("vector_int")
     .def (indexing::container_suite< std::vector<int> >());
+}
 

@@ -187,14 +199,14 @@ provides a hook for the def function to install multiple Python methods in one call. If the container element type (int in the example above) is a user-defined - type, you will have to expose this type to Python via a separate - class_ instance. + type, you would have to expose this type to Python via a + separate class_ instance.

[1] Automatic operation with the standard - containers works poperly if your compiler supports partial + containers works properly if your compiler supports partial template specializations. Otherwise, refer to the compiler workarounds section. @@ -239,9 +251,10 @@ namespace boost { namespace python { namespace indexing {

  1. - It relies on the indexing::algo_selector - template, which uses partial template specialization, to - select what functionality to provide for the container. + It does not include any of the container-specific headers + (like vector.hpp or set.hpp), so + these must be included separately to add support each type + of container.
  2. @@ -265,6 +278,24 @@ namespace boost { namespace python { namespace indexing {

    +

    Container-specific headers

    + +

    + + The container indexing suite includes support for many of the + standard C++ container templates, but note that the support code + for each is in a separate header file. These header files (in + the boost/python/suite/indexing subdirectory) are: + vector.hpp, deque.hpp, + list.hpp, set.hpp and + map.hpp. These correspond in the obvious way to the + standard headers vector, deque, + etc. The header files for the container_proxy and + iterator_range templates provide their own support + implicitly. + +

    +

    Using policies

    You can select call policies using the @@ -291,8 +322,9 @@ namespace boost { namespace python { namespace indexing { elements actually being referenced. Various alternatives exist, the best of which is to store the container elements indirectly, using boost::shared_ptr or an equivalent. If this - is not possible, container_proxy may provide a + is not possible, + container_proxy + may provide a solution, at least for vector-like containers.

    @@ -508,14 +540,14 @@ static void visitor_helper (PythonClass &, Policy const &); In order to include a custom ValueTraits class into the container suite, it is easiest to supply it as a specialization of the template - indexing::value_traits for the container's - element type. The existing ContainerTraits classes - all make use of + indexing::value_traits for the container's element + type. The existing ContainerTraits classes all + make use of value_traits<container::value_type>, and so will use a specialization for the value type if available. The default, unspecialized, version of value_traits - defines equality_comparable as true - and has an empty implementation of visitor_helper. + sets both of the static constants to true and has + an empty implementation of visitor_helper.

    @@ -770,7 +802,7 @@ namespace boost { namespace python { namespace indexing { index_style - enum index_style_t + index_style_t @@ -1070,8 +1102,8 @@ namespace boost { namespace python { namespace indexing {

     #include <map>
     #include <string>
    -#include <boost/python/suite/indexing/iterator_traits.hpp>
    -// Include iterator_traits to get index_style_t
    +#include <boost/python/suite/indexing/suite_utils.hpp>
    +// Include suite_utils to get index_style_t
     
     struct simple_map_traits {
       // Traits information for std::map<std::string, int>
    @@ -1160,8 +1192,8 @@ BOOST_PYTHON_MODULE(test_simple) {
           
    1. - The functions should be static, with container - & as first parameter. + The functions should be static, with + container & as first parameter.
    2. @@ -1328,7 +1360,9 @@ namespace boost { namespace python { namespace indexing { Similar to the above (in fact, it derives from default_algorithms) except that it uses container member functions reverse and - sort instead of the iterator-based versions. + sort instead of the iterator-based + versions. Defined in + boost/python/suite/indexing/list.hpp. @@ -1460,23 +1494,23 @@ struct my_algorithms - Algorithms:: -make_slice_helper -(c, s) + Algorithms:: make_slice_helper + (c, s) - Algorithms:: -slice_helper + Algorithms:: slice_helper + c is of type + Algorithms:: container & and + s is of type indexing:: + slice const &. Returns a newly constructed slice_helper - object by value, where c is of type - Algorithms::container & and s is - of type indexing::slice const &. + object by value. @@ -1484,8 +1518,7 @@ slice_helper - slice_helper. -next() + slice_helper.next() @@ -1507,29 +1540,26 @@ next() - slice_helper. -current() + slice_helper. current() - Algorithms:: -reference + Algorithms:: reference Returns a reference to the current element of the - slice. This will only be called after a prior successful - call to next(). + slice. This will only be called if the last call to + next() returned true. - slice_helper. -write (v) + slice_helper.write (v) @@ -1539,23 +1569,23 @@ write (v) - Advances to the next element of the slice, as defined in + The parameter v is of type + Algorthims::value_param. Advances to the + next element of the slice, as defined in next, and writes the given value - v at the new location in the - container. v will be convertible to - Algorthims::value_param. If the slice is - exhausted (i.e. next would return false) then - write either inserts the value into - the container at the next location (past the end of the - slice), or sets a Python exception and throws. + v at the new location in the container.If the + slice is exhausted (i.e. next would return + false) then write either inserts the + value into the container at the next location (past the + end of the slice), or sets a Python exception and + throws. - slice_helper. -erase_remaining() + slice_helper. erase_remaining() @@ -1597,8 +1627,10 @@ erase_remaining() The container_proxy template provides an emulation of Python reference semantics for objects held by value in a - vector-like container. The primary application of this template - is in situations where all of the following apply: + vector-like container. Of course, this introduces some + performance penalties in terms of memory usage and run time, so + the primary application of this template is in situations where + all of the following apply:
      1. @@ -1615,7 +1647,7 @@ erase_remaining()
      2. - Element insertion, deletion or assignment are common, so + Element insertion, deletion or assignment takes place, so that using return_internal_reference would be dangerous. @@ -1627,20 +1659,32 @@ erase_remaining()

        - The container_proxy template wraps a vector-like - container and presents an interface that is similar to that of a - normal vector, but which returns element_proxy - objects instead of plain references to values stored in the - wrapped container. During an operation that alters the position - of an element within the container (e.g. insert) - the container_proxy code updates the relevant proxy - objects, so that they still refer to the original elements of - the container. Any operation that would delete or overwrite a - value in the container (e.g. erase) copies the - to-be-deleted value into its corresponding proxy object. This - means that a proxy's "reference" to an element is robust in the - face of changes to the element's position in the container, and - even that element's removal. + The container_proxy template wraps any vector-like + container and presents an interface that is similar to that of + std::vector, but which returns + element_proxy objects instead of plain references + to values stored in the wrapped container. During an operation + that alters the position of an element within the container + (e.g. insert) the container_proxy code + updates the relevant proxy objects, so that they still refer to + the same elements at their new locations. Any operation + that would delete or overwrite a value in the container + (e.g. erase) copies the to-be-deleted value into + its corresponding proxy object. This means that a proxy's + "reference" to an element is robust in the face of changes to + the element's position in the container, and even the element's + removal. + +

        +

        + + Ideally, any code that changes the positions of elements within + the container would use only the container_proxy + interface, to ensure that the proxies are maintained in + synchronization. Code that otherwise makes direct modifications + to the raw container must notify the + container_proxy of the changes, as detailed in the + following section.

        @@ -1648,37 +1692,79 @@ erase_remaining()

        - The container_proxy interface is designed to be - convenient to use from C++, and to inter-operate with the - default_algorithms template. It is important that - any code that changes element positions within the - container (at least while proxies for the container exist) uses - the container_proxy interface, to ensure that the - proxies get updated. Of course, the interface introduces some - performance penalties, both in terms of memory usage and run - time. + The container_proxy template takes three + parameters, only the first of which is mandatory:

        - The Holder template parameter determines how the - container_proxy stores the raw container object. - There are currently two types of holder implemented, the default - identity template which stores it's argument by - value, and the deref template which stores a - (plain) pointer to an external object. It would be possible, for - instance, to create a holder that uses a - shared_pointer instead. +

        +template<class Container
        +       , class Holder = identity<Container>
        +       , class Generator = vector_generator> class container_proxy;
        +

        +

        + The Container argument is the raw container type + that the container_proxy will manage. It must + provide random-access indexing. + +

        +

        + + The Holder argument determines how the + container_proxy stores the raw container object. + There are currently two types of holder implemented, the default + identity template which will store the raw + container by value within the container_proxy, and + the deref template which stores a (plain) pointer + to an external object. It would also be possible, for instance, + to create a holder that uses a shared_pointer, or + one that stores a pointer but performs deep copies. + +

        +

        + + The Generator argument determines what container to + use for storing the proxy objects. The argument must be a + suitable class so that + Generator::apply<proxy_t>::type is a typedef + for the container to use for storing the proxies. The default is + vector_generator, which generates + std::vector instances. The usefulness of allowing + other generators can be seen from the example + + container_proxy<std::deque<...> >. + + Insertion at the beginning of this container_proxy + requires an insertion at the beginning of the + std::deque raw container, which has amortized + constant time complexity. However, it also requires an insertion + at the beginning of the proxy container, which (using the + std::vector provided by + vector_generator) has linear time complexity. If + this is a significant issue, you can use a custom + Generator to match the performance characteristics + of the proxy container to those of the raw container. + +

        +

        + + Examples in libs/python/test/test_container_proxy.cpp + ... + +

        Synopsis: boost/python/suite/indexing/container_proxy.hpp

         namespace boost { namespace python { namespace indexing {
           template<class Container
        -  	 , class Holder = identity<Container> >
        +         , class Holder = identity<Container>
        +         , class Generator = vector_generator>
           class container_proxy
           {
           public:
        @@ -1690,12 +1776,12 @@ namespace boost { namespace python { namespace indexing {
         
             typedef implementation defined value_type;
             typedef implementation defined const_value_type;
        +    typedef implementation defined iterator;
        +    typedef implementation defined const_iterator;
         
             typedef value_type        reference;       // Has reference semantics
             typedef const_value_type  const_reference; // Has reference semantics
         
        -    struct iterator { implementation defined }
        -
             container_proxy ();
             explicit container_proxy (held_type const &);
             template<typename Iter> container_proxy (Iter, Iter);
        @@ -1725,8 +1811,15 @@ namespace boost { namespace python { namespace indexing {
             template<typename Iter> void insert (iterator, Iter, Iter);
         
             void push_back (raw_value_type const &);
        -
             value_type pop_back ();
        +
        +    // These functions are not normally necessary. They notify the
        +    // container_proxy of changes to the raw container made by other
        +    // code (see documentation for details)
        +    void detach_proxy (size_type index);
        +    void detach_proxies (size_type from, size_type to);
        +    void prepare_erase (size_type from, size_type to);
        +    void notify_insertion (size_type from, size_type to);
           };
         } } }
         
        @@ -1751,7 +1844,7 @@ namespace boost { namespace python { namespace indexing {

    -

    +

    The deref template.

    @@ -1773,6 +1866,21 @@ namespace boost { namespace python { namespace indexing {
     

    +

    + The vector_generator class. + +

    +namespace boost { namespace python { namespace indexing {
    +  struct vector_generator {
    +    template<typename Element> struct apply {
    +      typedef std::vector<Element> type;
    +    };
    +  };
    +} } }
    +
    +

    + +

    container_proxy implementation notes

    @@ -1783,9 +1891,8 @@ namespace boost { namespace python { namespace indexing { has a pointer back to the container_proxy object and an element index within the wrapped container. This can be seen in the following diagram, which shows a - container_proxy< vector<int> - > containing the three elements 111, 222 and - 333. + container_proxy< vector<int> > + containing the three elements 111, 222 and 333.

    @@ -1793,17 +1900,17 @@ namespace boost { namespace python { namespace indexing { - Interrelations between container_proxy, its container
-          and its element proxies + and an element proxy"> - Diagram 2. Example of container_proxy with some - element proxies + Diagram 2. Example of container_proxy with an + element proxy @@ -1814,12 +1921,12 @@ namespace boost { namespace python { namespace indexing { In the example above, the shown element_proxy object refers (indirectly) to the container element with the value 222. An insertion before this element would increment the - element numbers in the shared_proxy objects so that + index numbers in the shared_proxy objects so that the given element_proxy continues to refer to the same value at its new location. Similary, a deletion before the element would decrement the affected shared_proxy - element numbers. If the referenced element itself gets deleted - or overwritten, the shared_proxy first takes a + indexes. If the referenced element itself gets deleted or + overwritten, the shared_proxy first takes a copy of the original value, and is then considered to be detached from the container_proxy. This situation is shown below in diagram 3. @@ -1975,15 +2082,19 @@ namespace boost { namespace python { namespace indexing {

    The following Python sequence and mapping functions are not - currently implemented for any containers: keys, values, - items, clear, copy, update, pop, __add__, __radd__, __iadd__, - __mul__, __rmul__ and __imul__. Most of the methods - mentioned (except for pop) present no particular - difficulty to implement. The problem with pop is - that it is incompatible with some return value policies (for - instance, return_internal_reference) since it must - return a copy of an element that has already been removed from - the container. This probably requires an extension to the + currently implemented for any containers: + + keys, values, items, clear, copy, update, + pop, __add__, __radd__, __iadd__, __mul__, __rmul__ + and __imul__. + + Most of the methods mentioned (except for pop) + present no particular difficulty to implement. The problem with + pop is that it is incompatible with some return + value policies (for instance, + return_internal_reference) since it must return a + copy of an element that has already been removed from the + container. This probably requires an extension to the container_suite interface, to allow the client code the option of specifying a different return policy for this method in particular. @@ -2032,18 +2143,19 @@ namespace boost { namespace python { namespace indexing {

    Thanks to Joel de Guzman and David Abrahams for input and - encouragement during the development of the container - suite. Joel wrote the original implementation of the indexing - support, which provided many of the ideas embodied in the new - implementation. + encouragement during the development of the container suite, and + to and Ralf W. Grosse-Kunstleve for his invaluable support in + porting to various platforms. Joel wrote the original + implementation of the indexing support, which provided many of + the ideas embodied in the new implementation.

    The container suite code and documentation are Copyright (c) - 2003 by Raoul Gough, and licensed under the current Boost - license. + 2003 by Raoul Gough, and licensed according to the Boost license.