From 5eaf3a0e88b9bb7afde3e045b163187d92c28df6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorsten=20J=C3=B8rgen=20Ottosen?= Date: Mon, 21 Mar 2005 00:01:27 +0000 Subject: [PATCH] *** empty log message *** [SVN r27749] --- .gitattributes | 96 ++++ doc/associative_ptr_container.html | 248 +++++++++ doc/associative_ptr_container.rst | 217 ++++++++ doc/cboost.gif | Bin 0 -> 8819 bytes doc/comp.sh | 6 + doc/comp_all.sh | 26 + doc/comp_associative_ptr_container.sh | 2 + doc/comp_conventions.sh | 1 + doc/comp_examples.sh | 2 + doc/comp_faq.sh | 2 + doc/comp_guidelines.sh | 2 + doc/comp_headers.sh | 2 + doc/comp_indirect_fun.sh | 2 + doc/comp_ptr_array.sh | 2 + doc/comp_ptr_container.sh | 2 + doc/comp_ptr_deque.sh | 2 + doc/comp_ptr_list.sh | 2 + doc/comp_ptr_map.sh | 2 + doc/comp_ptr_map_adapter.sh | 2 + doc/comp_ptr_multimap.sh | 2 + doc/comp_ptr_multimap_adapter.sh | 2 + doc/comp_ptr_multiset.sh | 2 + doc/comp_ptr_multiset_adapter.sh | 2 + doc/comp_ptr_sequence_adapter.sh | 2 + doc/comp_ptr_set.sh | 2 + doc/comp_ptr_set_adapter.sh | 2 + doc/comp_ptr_vector.sh | 2 + doc/comp_reference.sh | 1 + doc/comp_reversible_ptr_container.sh | 2 + doc/comp_tutorial.sh | 2 + doc/conventions.html | 114 +++++ doc/conventions.rst | 102 ++++ doc/default.css | 248 +++++++++ doc/examples.html | 689 ++++++++++++++++++++++++++ doc/examples.rst | 170 +++++++ doc/faq.html | 104 ++++ doc/faq.rst | 94 ++++ doc/guidelines.html | 36 ++ doc/guidelines.rst | 29 ++ doc/headers.html | 83 ++++ doc/headers.rst | 47 ++ doc/indirect_fun.html | 126 +++++ doc/indirect_fun.rst | 123 +++++ doc/intro.xml | 79 +++ doc/ptr_array.html | 254 ++++++++++ doc/ptr_array.rst | 237 +++++++++ doc/ptr_container.html | 224 +++++++++ doc/ptr_container.rst | 189 +++++++ doc/ptr_container.xml | 43 ++ doc/ptr_deque.html | 153 ++++++ doc/ptr_deque.rst | 150 ++++++ doc/ptr_list.html | 146 ++++++ doc/ptr_list.rst | 135 +++++ doc/ptr_map.html | 56 +++ doc/ptr_map.rst | 54 ++ doc/ptr_map_adapter.html | 158 ++++++ doc/ptr_map_adapter.rst | 139 ++++++ doc/ptr_multimap.html | 54 ++ doc/ptr_multimap.rst | 52 ++ doc/ptr_multimap_adapter.html | 134 +++++ doc/ptr_multimap_adapter.rst | 135 +++++ doc/ptr_multiset.html | 58 +++ doc/ptr_multiset.rst | 55 ++ doc/ptr_multiset_adapter.html | 122 +++++ doc/ptr_multiset_adapter.rst | 116 +++++ doc/ptr_sequence_adapter.html | 328 ++++++++++++ doc/ptr_sequence_adapter.rst | 323 ++++++++++++ doc/ptr_set.html | 59 +++ doc/ptr_set.rst | 55 ++ doc/ptr_set_adapter.html | 122 +++++ doc/ptr_set_adapter.rst | 115 +++++ doc/ptr_vector.html | 158 ++++++ doc/ptr_vector.rst | 144 ++++++ doc/reference.html | 389 +++++++++++++++ doc/reference.rst | 350 +++++++++++++ doc/reversible_ptr_container.html | 468 +++++++++++++++++ doc/reversible_ptr_container.rst | 431 ++++++++++++++++ doc/todo.txt | 71 +++ doc/tut1.html | 357 +++++++++++++ doc/tut2.html | 176 +++++++ doc/tutorial.html | 332 +++++++++++++ doc/tutorial.rst | 333 +++++++++++++ index.html | 17 + test/Jamfile | 33 ++ test/Jamfile.v2 | 9 + test/algo_test_data.hpp | 37 ++ test/associative_test_data.hpp | 125 +++++ test/cast.cpp | 6 + test/concept_check_data.hpp | 12 + test/convert.cpp | 36 ++ test/incomplete_type_test.cpp | 176 +++++++ test/indirect_fun.cpp | 61 +++ test/indirect_vector.cpp | 109 ++++ test/map_value_iterator.cpp | 118 +++++ test/null_object.cpp | 243 +++++++++ test/pointainer_speed.cpp | 194 ++++++++ test/ptr_array.cpp | 157 ++++++ test/ptr_container_adapter.cpp | 59 +++ test/ptr_deque.cpp | 24 + test/ptr_list.cpp | 27 + test/ptr_map.cpp | 225 +++++++++ test/ptr_map_adapter.cpp | 58 +++ test/ptr_set.cpp | 37 ++ test/ptr_unordered_map.cpp | 57 +++ test/ptr_unordered_set.cpp | 46 ++ test/ptr_vector.cpp | 55 ++ test/ptr_vector_size.cpp | 15 + test/sequence_point.cpp | 52 ++ test/sequence_test_data.hpp | 118 +++++ test/simple_test.cpp | 95 ++++ test/stack_example.cpp | 25 + test/test_data.hpp | 201 ++++++++ test/tree_test.cpp | 270 ++++++++++ test/tut1.cpp | 342 +++++++++++++ test/tut34.cpp | 50 ++ test/tut5.cpp | 1 + test/vector_size.cpp | 15 + test/view_example.cpp | 160 ++++++ test/xml_tree_test.cpp | 173 +++++++ 119 files changed, 12996 insertions(+) create mode 100644 .gitattributes create mode 100644 doc/associative_ptr_container.html create mode 100755 doc/associative_ptr_container.rst create mode 100644 doc/cboost.gif create mode 100644 doc/comp.sh create mode 100644 doc/comp_all.sh create mode 100644 doc/comp_associative_ptr_container.sh create mode 100644 doc/comp_conventions.sh create mode 100644 doc/comp_examples.sh create mode 100644 doc/comp_faq.sh create mode 100644 doc/comp_guidelines.sh create mode 100644 doc/comp_headers.sh create mode 100644 doc/comp_indirect_fun.sh create mode 100644 doc/comp_ptr_array.sh create mode 100644 doc/comp_ptr_container.sh create mode 100644 doc/comp_ptr_deque.sh create mode 100644 doc/comp_ptr_list.sh create mode 100644 doc/comp_ptr_map.sh create mode 100644 doc/comp_ptr_map_adapter.sh create mode 100644 doc/comp_ptr_multimap.sh create mode 100644 doc/comp_ptr_multimap_adapter.sh create mode 100644 doc/comp_ptr_multiset.sh create mode 100644 doc/comp_ptr_multiset_adapter.sh create mode 100644 doc/comp_ptr_sequence_adapter.sh create mode 100644 doc/comp_ptr_set.sh create mode 100644 doc/comp_ptr_set_adapter.sh create mode 100644 doc/comp_ptr_vector.sh create mode 100644 doc/comp_reference.sh create mode 100644 doc/comp_reversible_ptr_container.sh create mode 100644 doc/comp_tutorial.sh create mode 100644 doc/conventions.html create mode 100755 doc/conventions.rst create mode 100755 doc/default.css create mode 100644 doc/examples.html create mode 100755 doc/examples.rst create mode 100644 doc/faq.html create mode 100755 doc/faq.rst create mode 100644 doc/guidelines.html create mode 100755 doc/guidelines.rst create mode 100644 doc/headers.html create mode 100755 doc/headers.rst create mode 100644 doc/indirect_fun.html create mode 100755 doc/indirect_fun.rst create mode 100644 doc/intro.xml create mode 100644 doc/ptr_array.html create mode 100755 doc/ptr_array.rst create mode 100644 doc/ptr_container.html create mode 100755 doc/ptr_container.rst create mode 100644 doc/ptr_container.xml create mode 100644 doc/ptr_deque.html create mode 100755 doc/ptr_deque.rst create mode 100644 doc/ptr_list.html create mode 100755 doc/ptr_list.rst create mode 100644 doc/ptr_map.html create mode 100755 doc/ptr_map.rst create mode 100644 doc/ptr_map_adapter.html create mode 100755 doc/ptr_map_adapter.rst create mode 100644 doc/ptr_multimap.html create mode 100755 doc/ptr_multimap.rst create mode 100644 doc/ptr_multimap_adapter.html create mode 100755 doc/ptr_multimap_adapter.rst create mode 100644 doc/ptr_multiset.html create mode 100755 doc/ptr_multiset.rst create mode 100644 doc/ptr_multiset_adapter.html create mode 100755 doc/ptr_multiset_adapter.rst create mode 100644 doc/ptr_sequence_adapter.html create mode 100755 doc/ptr_sequence_adapter.rst create mode 100644 doc/ptr_set.html create mode 100755 doc/ptr_set.rst create mode 100644 doc/ptr_set_adapter.html create mode 100755 doc/ptr_set_adapter.rst create mode 100644 doc/ptr_vector.html create mode 100755 doc/ptr_vector.rst create mode 100644 doc/reference.html create mode 100755 doc/reference.rst create mode 100644 doc/reversible_ptr_container.html create mode 100755 doc/reversible_ptr_container.rst create mode 100755 doc/todo.txt create mode 100755 doc/tut1.html create mode 100755 doc/tut2.html create mode 100644 doc/tutorial.html create mode 100755 doc/tutorial.rst create mode 100755 index.html create mode 100755 test/Jamfile create mode 100755 test/Jamfile.v2 create mode 100755 test/algo_test_data.hpp create mode 100755 test/associative_test_data.hpp create mode 100755 test/cast.cpp create mode 100755 test/concept_check_data.hpp create mode 100755 test/convert.cpp create mode 100755 test/incomplete_type_test.cpp create mode 100755 test/indirect_fun.cpp create mode 100755 test/indirect_vector.cpp create mode 100755 test/map_value_iterator.cpp create mode 100755 test/null_object.cpp create mode 100755 test/pointainer_speed.cpp create mode 100755 test/ptr_array.cpp create mode 100755 test/ptr_container_adapter.cpp create mode 100755 test/ptr_deque.cpp create mode 100755 test/ptr_list.cpp create mode 100755 test/ptr_map.cpp create mode 100755 test/ptr_map_adapter.cpp create mode 100755 test/ptr_set.cpp create mode 100755 test/ptr_unordered_map.cpp create mode 100755 test/ptr_unordered_set.cpp create mode 100755 test/ptr_vector.cpp create mode 100755 test/ptr_vector_size.cpp create mode 100755 test/sequence_point.cpp create mode 100755 test/sequence_test_data.hpp create mode 100755 test/simple_test.cpp create mode 100755 test/stack_example.cpp create mode 100755 test/test_data.hpp create mode 100755 test/tree_test.cpp create mode 100755 test/tut1.cpp create mode 100755 test/tut34.cpp create mode 100755 test/tut5.cpp create mode 100755 test/vector_size.cpp create mode 100755 test/view_example.cpp create mode 100755 test/xml_tree_test.cpp diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..3e84d7c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,96 @@ +* text=auto !eol svneol=native#text/plain +*.gitattributes text svneol=native#text/plain + +# Scriptish formats +*.bat text svneol=native#text/plain +*.bsh text svneol=native#text/x-beanshell +*.cgi text svneol=native#text/plain +*.cmd text svneol=native#text/plain +*.js text svneol=native#text/javascript +*.php text svneol=native#text/x-php +*.pl text svneol=native#text/x-perl +*.pm text svneol=native#text/x-perl +*.py text svneol=native#text/x-python +*.sh eol=lf svneol=LF#text/x-sh +configure eol=lf svneol=LF#text/x-sh + +# Image formats +*.bmp binary svneol=unset#image/bmp +*.gif binary svneol=unset#image/gif +*.ico binary svneol=unset#image/ico +*.jpeg binary svneol=unset#image/jpeg +*.jpg binary svneol=unset#image/jpeg +*.png binary svneol=unset#image/png +*.tif binary svneol=unset#image/tiff +*.tiff binary svneol=unset#image/tiff +*.svg text svneol=native#image/svg%2Bxml + +# Data formats +*.pdf binary svneol=unset#application/pdf +*.avi binary svneol=unset#video/avi +*.doc binary svneol=unset#application/msword +*.dsp text svneol=crlf#text/plain +*.dsw text svneol=crlf#text/plain +*.eps binary svneol=unset#application/postscript +*.gz binary svneol=unset#application/gzip +*.mov binary svneol=unset#video/quicktime +*.mp3 binary svneol=unset#audio/mpeg +*.ppt binary svneol=unset#application/vnd.ms-powerpoint +*.ps binary svneol=unset#application/postscript +*.psd binary svneol=unset#application/photoshop +*.rdf binary svneol=unset#text/rdf +*.rss text svneol=unset#text/xml +*.rtf binary svneol=unset#text/rtf +*.sln text svneol=native#text/plain +*.swf binary svneol=unset#application/x-shockwave-flash +*.tgz binary svneol=unset#application/gzip +*.vcproj text svneol=native#text/xml +*.vcxproj text svneol=native#text/xml +*.vsprops text svneol=native#text/xml +*.wav binary svneol=unset#audio/wav +*.xls binary svneol=unset#application/vnd.ms-excel +*.zip binary svneol=unset#application/zip + +# Text formats +.htaccess text svneol=native#text/plain +*.bbk text svneol=native#text/xml +*.cmake text svneol=native#text/plain +*.css text svneol=native#text/css +*.dtd text svneol=native#text/xml +*.htm text svneol=native#text/html +*.html text svneol=native#text/html +*.ini text svneol=native#text/plain +*.log text svneol=native#text/plain +*.mak text svneol=native#text/plain +*.qbk text svneol=native#text/plain +*.rst text svneol=native#text/plain +*.sql text svneol=native#text/x-sql +*.txt text svneol=native#text/plain +*.xhtml text svneol=native#text/xhtml%2Bxml +*.xml text svneol=native#text/xml +*.xsd text svneol=native#text/xml +*.xsl text svneol=native#text/xml +*.xslt text svneol=native#text/xml +*.xul text svneol=native#text/xul +*.yml text svneol=native#text/plain +boost-no-inspect text svneol=native#text/plain +CHANGES text svneol=native#text/plain +COPYING text svneol=native#text/plain +INSTALL text svneol=native#text/plain +Jamfile text svneol=native#text/plain +Jamroot text svneol=native#text/plain +Jamfile.v2 text svneol=native#text/plain +Jamrules text svneol=native#text/plain +Makefile* text svneol=native#text/plain +README text svneol=native#text/plain +TODO text svneol=native#text/plain + +# Code formats +*.c text svneol=native#text/plain +*.cpp text svneol=native#text/plain +*.h text svneol=native#text/plain +*.hpp text svneol=native#text/plain +*.ipp text svneol=native#text/plain +*.tpp text svneol=native#text/plain +*.jam text svneol=native#text/plain +*.java text svneol=native#text/plain diff --git a/doc/associative_ptr_container.html b/doc/associative_ptr_container.html new file mode 100644 index 0000000..edd6298 --- /dev/null +++ b/doc/associative_ptr_container.html @@ -0,0 +1,248 @@ + + + + + + + + + + +
+
+

Class associative_ptr_container

+

This section describes all the common operations for all associative +pointer containers (in addition to reversible_ptr_container):

+ +

See also:

+ +

Navigate:

+ +

Synopsis:

+
+namespace boost
+{
+    template
+    < 
+        class Key, 
+        class CloneAllocator = heap_clone_allocator 
+    >
+    class associative_ptr_container 
+    {
+    public: // typedefs
+        typedef ...   key_type;
+        typedef ...   key_compare;
+        typedef ...   value_compare;
+
+    public: // observers
+        key_compare    key_comp() const;
+        value_compare  value_comp() const;
+
+    public: // modifiers         
+        template< typename InputIterator >
+        void       insert( InputIterator first, InputIterator last );     
+        template< class InputRange >
+        void       insert( const InputRange& r );
+        void       erase( iterator position ); 
+        size_type  erase( const key_type& x );
+        template< class Range >
+        void       erase( const Range& r );
+        void       erase( iterator first, iterator last );
+
+    public: // algorithms
+        iterator                        find( const key_type& x );
+        const_iterator                  find( const key_type& x ) const;
+        size_type                       count( const key_type& x ) const;              
+        iterator                        lower_bound( const key_type& x );                     
+        const_iterator                  lower_bound( const key_type& x ) const;
+        iterator                        upper_bound( const key_type& x );                           
+        const_iterator                  upper_bound( const key_type& x ) const;
+        iterator_range<iterator>        equal_range( const key_type& x );                 
+        iterator_range<const_iterator>  equal_range( const key_type& x ) const;
+     
+    }; //  class 'associative_ptr_container'
+    
+} // namespace 'boost'  
+
+
+
+

Semantics

+
+

Semantics: typedefs

+
    +
  • typedef ... key_type;

    +
    +
      +
    • if we are dealing with a map, then simply the key type
    • +
    • if we are dealing with a set, then the indirected key type, that is, +given ptr_set<T>, key_type* will be T*.
    • +
    +
    +
  • +
  • typedef ... key_compare;

    +
    +
      +
    • comparison object type that determines the order of elements in the container
    • +
    +
    +
  • +
  • typedef ... value_compare;

    +
    +
      +
    • comparison object type that determines the order of elements in the container
    • +
    • if we are dealing with a map, then this comparison simply forwards to the key_compare comparison operation
    • +
    +
    +
  • +
+
+
+

Semantics: observers

+
    +
  • key_compare key_comp() const;

    +
  • +
  • value_compare value_comp() const;

    +
    +
      +
    • returns copies of objects used to determine the order of elements
    • +
    +
    +
  • +
+
+
+

Semantics: modifiers

+
    +
  • template< typename InputIterator > +void insert( InputIterator first, InputIterator last );

    +
    +
      +
    • Requirements: [first,last) is a valid range
    • +
    • Effects: Inserts a cloned range
    • +
    • Exception safety: Basic guarantee
    • +
    +
    +
  • +
  • template< class InputRange > +void insert( const InputRange& r );

    +
    +
      +
    • Effects: insert( boost::begin(r), boost::end(r) );
    • +
    +
    +
  • +
  • void erase( iterator position );

    +
    +
      +
    • Requirements: position is a valid iterator from the container
    • +
    • Effects: Removes the element defined by position.
    • +
    • Throws: Nothing
    • +
    +
    +
  • +
  • size_type erase( const key_type& x );

    +
    +
      +
    • Effects: Removes all the elements in the container with a key equivalent to x and returns the number of erased elements.
    • +
    • Throws: Nothing
    • +
    +
    +
  • +
  • void erase( iterator first, iterator last );

    +
    +
      +
    • Requirements: [first,last) is a valid range
    • +
    • Effects: Removes the range of elements defined by [first,last).
    • +
    • Throws: Nothing
    • +
    +
    +
  • +
  • template< class Range > void erase( const Range& r );

    +
    +
      +
    • Effects: erase( boost::begin(r), boost::end(r) );
    • +
    +
    +
  • +
+
+
+

Semantics: algorithms

+
    +
  • iterator       find( const Key& x );

    +
  • +
  • const_iterator find( const Key& x ) const;

    +
    +
      +
    • Effects: Searches for the key and returns end() on failure.
    • +
    • Complexity: Logarithmic
    • +
    +
    +
  • +
  • size_type count( const Key& x ) const;

    +
    +
      +
    • Effects: Counts the elements with a key equivalent to x
    • +
    • Complexity: Logarithmic
    • +
    +
    +
  • +
  • iterator       lower_bound( const Key& x );

    +
  • +
  • const_iterator lower_bound( const Key& x ) const;

    +
    +
      +
    • Effects: Returns an iterator pointing to the first element with a key not less than x
    • +
    • Complexity: Logarithmic
    • +
    +
    +
  • +
  • iterator       upper_bound( const Key& x );

    +
  • +
  • const_iterator upper_bound( const Key& x ) const;

    +
    +
      +
    • Effects: Returns an iterator pointing to the first element with a key greater than x
    • +
    • Complexity: Logarithmic
    • +
    +
    +
  • +
  • iterator_range<iterator>       equal_range( const Key& x );

    +
  • +
  • iterator_range<const_iterator> equal_range( const Key& x ) const;

    +
    +
      +
    • Effects: return boost::make_iterator_range( lower_bound( x ), upper_bound( x ) );
    • +
    • Complexity: Logarithmic
    • +
    +
    +
  • +
+ +
+
+
+ + diff --git a/doc/associative_ptr_container.rst b/doc/associative_ptr_container.rst new file mode 100755 index 0000000..abfccbf --- /dev/null +++ b/doc/associative_ptr_container.rst @@ -0,0 +1,217 @@ +Class ``associative_ptr_container`` +------------------------------------- + +This section describes all the common operations for all associative +pointer containers (in addition to ``reversible_ptr_container``): + +- ptr_map_adapter_ +- ptr_multimap_adapter_ +- ptr_map_ +- ptr_multimap_ +- ptr_set_adapter_ +- ptr_multiset_adapter_ +- ptr_set_ +- ptr_multiset_ + +.. _ptr_map_adapter : ptr_map_adapter.html +.. _ptr_multimap_adapter: ptr_multimap_adapter.html +.. _ptr_map: ptr_map.html +.. _ptr_multimap: ptr_multimap.html +.. _ptr_set_adapter: ptr_set_adapter.html +.. _ptr_multiset_adapter: ptr_multiset.html +.. _ptr_set: ptr_set.html +.. _ptr_multiset: ptr_multiset.html + +**See also:** + +- reversible_ptr_container__ +- `iterator_range `_ + +__ reversible_ptr_container.html + +**Navigate:** + +- `home `_ +- `reference `_ + +**Synopsis:** + +.. parsed-literal:: + + namespace boost + { + template + < + class Key, + class CloneAllocator = heap_clone_allocator + > + class associative_ptr_container + { + public: // typedefs_ + typedef ... key_type; + typedef ... key_compare; + typedef ... value_compare; + + public: // `observers`_ + key_compare key_comp() const; + value_compare value_comp() const; + + public: // `modifiers`_ + template< typename InputIterator > + void insert( InputIterator first, InputIterator last ); + template< class InputRange > + void insert( const InputRange& r ); + void erase( iterator position ); + size_type erase( const key_type& x ); + template< class Range > + void erase( const Range& r ); + void erase( iterator first, iterator last ); + + public: // `algorithms`_ + iterator find( const key_type& x ); + const_iterator find( const key_type& x ) const; + size_type count( const key_type& x ) const; + iterator lower_bound( const key_type& x ); + const_iterator lower_bound( const key_type& x ) const; + iterator upper_bound( const key_type& x ); + const_iterator upper_bound( const key_type& x ) const; + iterator_range equal_range( const key_type& x ); + iterator_range equal_range( const key_type& x ) const; + + }; // class 'associative_ptr_container' + + } // namespace 'boost' + + +Semantics +--------- + +.. _typedefs: + +Semantics: typedefs +^^^^^^^^^^^^^^^^^^^ + +- ``typedef ... key_type;`` + + - if we are dealing with a map, then simply the key type + - if we are dealing with a set, then the *indirected* key type, that is, + given ``ptr_set``, ``key_type*`` will be ``T*``. + +- ``typedef ... key_compare;`` + + - comparison object type that determines the order of elements in the container + +- ``typedef ... value_compare;`` + + - comparison object type that determines the order of elements in the container + - if we are dealing with a map, then this comparison simply forwards to the ``key_compare`` comparison operation + +.. _`observers`: + +Semantics: observers +^^^^^^^^^^^^^^^^^^^^ + +- ``key_compare key_comp() const;`` +- ``value_compare value_comp() const;`` + + - returns copies of objects used to determine the order of elements + +.. _`modifiers`: + +Semantics: modifiers +^^^^^^^^^^^^^^^^^^^^ + +- ``template< typename InputIterator > + void insert( InputIterator first, InputIterator last );`` + + - Requirements: ``[first,last)`` is a valid range + + - Effects: Inserts a cloned range + + - Exception safety: Basic guarantee + +- ``template< class InputRange > + void insert( const InputRange& r );`` + + - Effects: ``insert( boost::begin(r), boost::end(r) );`` + +- ``void erase( iterator position );`` + + - Requirements: ``position`` is a valid iterator from the container + + - Effects: Removes the element defined by ``position``. + + - Throws: Nothing + +- ``size_type erase( const key_type& x );`` + + - Effects: Removes all the elements in the container with a key equivalent to ``x`` and returns the number of erased elements. + + - Throws: Nothing + +- ``void erase( iterator first, iterator last );`` + + - Requirements: ``[first,last)`` is a valid range + + - Effects: Removes the range of elements defined by ``[first,last)``. + + - Throws: Nothing + +- ``template< class Range > void erase( const Range& r );`` + + - Effects: ``erase( boost::begin(r), boost::end(r) );`` + +.. _`algorithms`: + +Semantics: algorithms +^^^^^^^^^^^^^^^^^^^^^ + +- ``iterator find( const Key& x );`` +- ``const_iterator find( const Key& x ) const;`` + + - Effects: Searches for the key and returns ``end()`` on failure. + + - Complexity: Logarithmic + +- ``size_type count( const Key& x ) const;`` + + - Effects: Counts the elements with a key equivalent to ``x`` + + - Complexity: Logarithmic + +- ``iterator lower_bound( const Key& x );`` +- ``const_iterator lower_bound( const Key& x ) const;`` + + - Effects: Returns an iterator pointing to the first element with a key not less than ``x`` + + - Complexity: Logarithmic + +- ``iterator upper_bound( const Key& x );`` +- ``const_iterator upper_bound( const Key& x ) const;`` + + - Effects: Returns an iterator pointing to the first element with a key greater than ``x`` + + - Complexity: Logarithmic + +- ``iterator_range equal_range( const Key& x );`` +- ``iterator_range equal_range( const Key& x ) const;`` + + - Effects: ``return boost::make_iterator_range( lower_bound( x ), upper_bound( x ) );`` + + - Complexity: Logarithmic + +.. + - ``reference at( const key_type& key );`` + - ``const_reference at( const key_type& key ) const;`` + + - Requirements: the key exists + + - Effects: returns the object with key ``key`` + + - Throws: ``bad_ptr_container_operation`` if the key does not exist + + +.. _`pointer container requirements`: + + + diff --git a/doc/cboost.gif b/doc/cboost.gif new file mode 100644 index 0000000000000000000000000000000000000000..58be431a3fafbd5adfa01e829ce8d80a03a83ed0 GIT binary patch literal 8819 zcmZ?wbhEHb6lDx!_|CwzZQFbH(K6ngWKJ ziiVnsJ(`+|nwo~1nogRU#hRMcnwmYDhC!N^Q#37?YC7%JbULQ#bxbqrnr8BQL(ODE zLoY+8V}?P;41=y2MlCgrx@H*l+%Wl?Ve)gs?C+L}mX?N=mWDx=hSipqQ!JgPSURn> z^vbpjT56g6-Lm?-WzTmf!(=DJY9}WzC#NVUr)(#u7ALR0PC?a9L35m__ikjmUwbv`^m{;;Wuj=n!J>P?zs)M|u zg1oYWg0h2x<^%<;4T`!KlsqLUd1+Ac+Mw)XLD|=WvhM|DKM$(D7F7K{sO5W5&-0+3 z??H3EM|mYj1#OK2ftIN3wNcggqSpRT4$4lBTAG}kot#{qoIE8tyC*q&PIC6vOS7xD zW>??KZaJ6Tb1u8*UUtv(>?z-~m%h(F_CNdD|Kj4M#l`1}=X@_-`@MMU_u_NktBZT8 zpp&i(JHp3~FQ z(gOl>dV03@^c?G%^1f%zxt=-KdX`@6S^B(Z>-#A^bEeFhGiA=&DRcHtS^9j+()UxA zexI`S-juEHr|f+`W$$+oI`@ChoO5&5URye6?b11Wmo7cFbm_UJOYbdRyLai)y3n&#m2hZSB_QYmePqd+hz%bMM!l`@Z(t_qETz@7;S2jPC8- z`+V=-_j~t#-+S!X-gEc%o_oLd-1lQ!uN`~-{oJ{G=gz%9ckkZ0d+*QP`+n{H_iNw3 z-@Etx-o5Y7LE!uQ=ilFd2LZ*OEQ|~c{~2^ZSpk$M7&!hh{O6SM*s$PWGl#HN%!v&P z54Q^_d(H9KxaerNgmKoL6B`#F?^kf{lJVTM)Z?TNcv$a| zX8p~bZNB0Df&T~6_*U;Ue!k)Nx4)0STN=lnoy=Uk&wHlPgHtoufA^>{GB7Z*NC+qx zEcpIN;8}uG+nxy)Z*Fk5pN`YwZ+XkW@@A=`LV`o-eI~Cj)^QWQ-oG;S@4wD($Mp*; zKP`6s{@DHBpR&r|f1Y;l*S~LH`{mvB-SzM1@2UKMVR3)O&lAhfXRyDTtWf>OAmU!t zs=u54Gam$&%`7~<@(I8EdENsIoYf18T1uH!F5G5d%-B3PRcBIqc*K(2v|IK+EpEtF zvVWTFZ*Tf*@q*YTCzbu}KZ#iM+uB`wtUT%073U>3|4u$WZ{ub)vwzYj1 zuldQd;&D~NvF-O#<}b8Nu8>@&;-9;Xcf)NZMy&}m=Ir4$;7VZmncQc2tKjgwqRO9N zm2B@69PXQ`ze#LXi_kW+n@esNs@-bIFpJ8}njN-lZftLp)yfr%lw4wFt350_kh}L| z+bR2hhkXvb%G=Y~cylrH%;s)`%pM)00cDHCB8v?zgnNb(GKA z#VV6;>)Rcd&s%@~^7x$1zd6b0?C$^iIo0ykHf4VM&pV8lZu@Lu*+1oT!|Hxpf4|Hp zebJ9zByaeB$KplThPhp@+}w7ws^{-I@aj&~7QP3E9IP%KooDK%P!P@VoTuVR?H94` zCpNd97&Ruj`*iYECj5P=JLyHiW`FayIluYr-`yzgH@o}hbD!0}CB}K?FTZT=v;Hk} z*Wb!~J9CMZ>G{tyuKeBLtiR*imCgMV{z~j#(jUWiC!yMCQ>B4B)0tJb8Fs#D?q0)q z;wM8smqL1^eT~I-iGN!rN2$G9{?}&G>8NXw2Oq>Pd~2*xz3{8?!x??n>n!ZQoBUAi z{}dgt z+CLsYPp}lKr}0kz_UE(Cjeixn=arWW*d5?Mdt3Fq+0Tf_yms$*G@rM4{ATfKgFi9M z=WOo^IQyI4zjJt>-Hn*T{Dw!KeD?kQBBq$%>gJQnz2<*jxcxrVXp+6cL-y^1<5sr{ z`AbdC%KXfjzPTZlzxu=CroTTf_WNC*B_^p;##iY5_F7rj>MP4aUq9$&K4+pK&+5n2 z!p(61TN3}pH%Ikq4zMyjF=2>~Y^(eCN8^~qA4a>{2K|ohC)^DWE#y!Acv#~4jpK$J zCh})UD9aza;A&SA$Xgq+QGWk|V|EKZcGtx$mio(a-29VaPu`tm*#{5Wr7lO9EI*qg z_x*>M{f@2fH8&SWOYE86f26Jd%#L$;3OOAdnOkRvpM0FMR_TBQhXG^Do5zBR5#60P z3bl5BIiCOT1+(6&VC{gj>ONC~C-i-q$Y1rM!|PW<>cn?T7pPrjwogoYI#uL~SMtlp zaz72i*j_HQ;AZM7j}w0CS{L;d zE~=m2vY1ct#=_Edu3C*3-sHVm(ags>fq^Mvq3pkZi{15F7V;NbD9dljIA%L#VNZ?D zV~H;}T(zDsa>iYGEV_O}yH-sgfBYUL`Bfc9ZFVf`kKOQS;hGc2^^z94q+D?pUozvk ze$T@GEC*-#>lH7}HwE_RS2WAr?r^g^wz03K#aZ@e#Bu9)AN$IGtZA#CBQ$x2iWPrW zvErQ=2W3_xMpmB(tM~#K=CTy=7u!5q-M^w)P^e6{jAyY(LaKY+pCi4wHck9VM_a$F zDG1wO*Cc%*fz5u(MV@MfWU1bpDlCu?UGugvkfU^sbp!| zxOzv6ZNkE?@*_%%jzze-_CD;3w@H>;ccIm0Rb%h%u*ci(Z)i6^RM?-tM_K;8hr-oY zM{UCTjyY-SaTHfRKD#%8%}iBUm67MdoiIZO^B$E338V5&x1MTFTCr?uCx;-H%JxUH z3mjamCnU1wGCUG~f1;7^%*8gxEy=u@8SPS66#7l>D9UDfd=vCC=+|Ac@aFuEb=*%9 zIm~Y?=AByMuBv0$e{@&!#tE^l)*+1Cl?xt;e2G};70%6*af4afD0ja3m4*E!OAgE5 z`6Sq&=A-;I!Rqqtvb-Xeq}~{nV=n90@#$AEa?1%Um{(T8W~i0E{Pl+oR>vIJbpBNZ zobUd>K=y9M@!IZReAOL?r4CPUtG%1ZS6F#C^R0us^@4AG_H!T0-2HKF{+)|`WhL+Z zZ%%Trf8MB5S+Ke~X!Z1l=NA(c6<5oCom90~-l(`LsX7Qzz_eLm>(Kl$h$PuI8) zit=SQw(GCB@s7b^!d0#lnQ}Hi99fkXH0=A|X!GNRb(OV21Bb-|^Vbg=IkYA;?BjP} zOgpjFT3{ka%=JgI3K@>(c7c@^42{wjKbowTENIR1P~?44&?L2MBdhL`IPPZ}i~{!< z+Y{eA@V@tOmcDn9&1OfkKwE~pVpBh-&z5GP=@$RAE(CH0Z%GyrOl{S9c91Li%wtKN zSU2-m{{$~rH$0ZEebc_^SL1`3yjeZ_&hE!-krc^Hi0k5 zfc3=%wjhC)tOtBYukkfIaO_D>ou0ti^_A=G0rm+O_>O;wIPih%^Ma^P2|W7^_&-kO zzgl4DdNuUz0vm=;hF=5Z3^ytHx0Z2z=dYb$c3#lD=7MLLBbWLX2BrgiiA?hPpEP5G zEWbE#EiaH(GGO=@e68ro2V>W*eBBi$uP*R1ec`>ff%j-a@Vy4UD+_pUU*LT(f$#PK zW2Ps(4=(V|?cn?WneTQ(*8>5*mkWwtEr?#9!S{;6l#j*KD!hcFh3`cI--#r?oipP9 zhVuVNjTaR0`N1T1ghgyVla}7KHUVM7tmpiy3DVmO)rBwk{X0;0c(ETx0&kfj-%108 z9|!oEGWvc981y%A2^ceQ8}KhI$nJ1xENb9*#K6Aj0-yH<#`_BFodfceGS$i1-_sS zY^S!dEi>nMaDc73fv>{hALm;Kj)@6;(>8FtNZ^{Tz`yzf=Vyn=Pan8DTX|Pc<$ZX- z?e+%#^)L7zFz9_vM z_8@^H^8w!!2aY!h98(MUY7$asU*%iL(7N#e_m>CUt3~-P9B@k#;VW!$xR<2=jmhS@ z#s|b=djli_8U=dYS(jurVFrU0lR}V3OrC3*TQKIBGXIrx@5i+%WI^ zVz&nkyr&I;v z0VMg!CJfaUiT*z>p;lt1tWCotY|UaQU=v)x6(_*H-(kYT3#=KhSe-8LIu$TqH(*gaz{@&;fvuD2 zUIU|s0AHa2>IQysDU<(UdLJJt z2^quLYa;mVo<-}ljZjS%Wn$&^PTy>D40HT z;OY6mp0=Qj=b`T230#{#aNiK%`x?n}@dMA52HyJ&yeAoWuNf@3Zm|7+K-V<~o{I&% z_Y&scci_G9p_Yw{PvVz-lefvPQu`MZ_~v);y;@KlaG9^3Nn_8B1+z3dUoh}LGf4b= zK{fG{Wg3&%xfea@&8wLe8FLiXc@)&c0=VuZ^s*GN**VDW6p(A(()&iRVTbh^rW0jP z7&u-8#JpX=Y}vrq&cJoSfLq`rU)}@O6Aer68?ZPF@H#(WJ*L1C_pgALCxGFC1Czl7 z9Tp>J@FH2$OfJ&0kVI$Zj~v;J(l!^Q`3hK^x}|>^FtIo=1_|wA?%17iQtqjN!s#eJ!6{sy8<;~s z@GTVJ+F!sU_>s@4fF~=8=T#JsvjF=A1s10U-dG04{R|9jA9&jv*lsH@NEECvy}%oI zfa!VxvmXO5ivjcX35=2#cqJDw-8En~e88*C!KZX`X7mSMKLytJ46KkTg##f!d za)BWsTq*JA1Kz0tk$W$2|6^LoPB zpPmbjZs5K0V8NXa_In+8I1CrO{E%SE%~R!v|B0im`Z;U?7n0ZldCCnqCqL!>b%A^T2L8k?_E#S8 zKWtE$V6D2aI8*17$dYV<35|TJA5QKP%;t1pteL=fw_%H}$eQOndS#cgzkR?laRJ|s zKYUgREUzYTF8si^R)Kwg!yfjD{3j>auqU!zSiRo)1J`A3mrq~$*sC}uF)#>z;FfY= zy;8s&yMa6K!>tny@!uTypCxbwC2&bCU^*YbEZM;KX*c&Ob%*|IdUrN(MK9o5tIivB zfMs`sz{&-zo&VNyi9h8&e}MmL0PnlW*QTiHrB%rD2`Sz&l=w4&yZ!;w-o!O(MJ(P2 zcq&VX9M=R3;3EB@aT!N zy>(#8{J^(Jpz-q$?zIg9KN>g!8U&tNv1~SAneXtJO_5(FflESxWxoLH>staF6S(vR zn0E; zD8*U$_%5SYW?)|9z`E&!z`7U>Ej)&uzoT&Iue(4Eo<2{8*p&xln+EBa!p*E-sEjR`CXb%?}vs9C+CS zc>)uTuzlq7ci>=8Thc|+W?27z4P~9K@Lgrrf@$`#({Ab*|TdmIDGqG%b)WqLkGG!L|KXgd_70Q?5T2mRp`*D&_ z@>F)I_nJZone%$HqnzpI921zQ4MoZiUy&->kjyTeJV| zTl#tWxx4!-KmWUW`n$jU{`$WX)^m1*d`dYr$u(`s^!H0nPWcyB_3s;xZv39q4|2Yn zzIRTtt=oO3^XI2^qAMyp9ril6WW+9t+TWzR^|)5woQR@53of5f?mJer=v>B$EM~_)l-R_Xznf6oeWzx^n@>{b0t*hncskrx`GWF}r z-|h43q`F^hI>qN=;Mgm6>y1iBT+#~J;wKZA&pmWUafK}B!N}*b1@|J^Wr_|7w$I7; zt5KV}^pB%DuT#X%Ba`w>PAPHs?y^)Ccrj^$o3iz~1@6k_#~hL;IaoQWPL1ul_;lu{ zd7ka_DnIRXpI@`?j=RHgxvCG2C$tuwa9};IQtaBT_j&o;vmXvFpI;sK>Wy4gRpURF zx#205?9-~>M5gqWe4B7|UVww7`icU(lge|7P6fL1pPHrU!e_baA_te>nnx^adgfI& zUFu2t;4IO%i<70n&+o%San%|HedVl@6;AWKk6m2OZ}%zks6=&KWt)7)yp89V<}rA? z%N=?ZsAE_s(VU@Vc)DeqPn#Fh=Y?f+?)J=|a&OOb@#2z)uJgQ7UK-5HJ1}Fhbfk-? zx?toX&Zoi!4wf!~hH8aNHihh&z`V2P-HKLA*LkNoW{EF3<-zG*_Tq$mkkrS6?RfzK zi)L)yccO7#VcNpweXhSMTc_5Ay!<*n>&MRZ^Y{M=JbvTQzmx0^+S0ev7cnkAYI%$4 ze2dSLdDs87w98g~n;5K6|7u~oT;-0<%jK%?RsMQewIFZ#Y*o`q%h}b9U#az)Y&)jG ztzi=NtjBP{?j)(+u9hXCeLp;pPS0B4c=VC){E6*ywHj~S?z!k$Bxs?Ch6K*n1cHi^2SLRI6N2b>kxI`y4o zyWWeBTnRUvB^xKXGX6{a$XVU+PByH-#VCbwxAUDuqyj`)%|(fb0UMCF;o@~$nC z4L=wc)LnVw{jOQbFz{ZQmDd6De@%cIkli+R?R2an})b{&`e_^_|6 zhFMB#rMr~Q3PC3yrgDjov)uMA?DEKHkxt&w<`xpzn_8nRxoQT>CkrF~*d>SZBo?w+ z?Fu|n7o#a3d8^%N%MyVOlO^eaEKg@}Jz1*eH&N-wg5$s5IPz3^D9ii_U^98v*mIiE zS@N5rtL=>~-sj(J>X{(W>-OiLW1oQ0av7aH9ty{%P0aRKC}b|x_}PG|CH_kT`~C+9 z`P3Ra+|!P*r!d@h-KEH8@F7`r^#gVlzk~em{xU@zUEyzjL2zHmpT(*FBce7jg=|i1 zy)<9)rq6VbLlX>2k11Z*;AXc+u&=u2vBZlV$DWog>^5mSEI0S{QvHvD{jvX;L=WY- z8ya6SNr^fl^rS)7*hR}Pf=5l+@4;2$GmgFaC5t5%XS5_532_J?xS(`-gOmKW<6X6H z4vGEKXfu4~%v&GQyzf&m*TY){h!&qb{Ur2BZ`q(`y zc8OfiiEy_r#m+-sDN^@09JiIawAI;rj^bTUw$0(J=ZP#j)z%h&day9b}a6P@?2ydR3y8pG#d0= zVV2oj5oW$XaLI&*$KpLZIqan_HqDN0>Ak7Tro88b+P@1|ZWs$6JnnKue8F*D?b=?) zjkV6wYB_JG7cyo|*fwR4d8Nn_h0HhaqUXA~?P_}5C;rksq}8)0KIJ=4+JzJPlRk34 z=(@}kzV1Xqec{?8jE8tS4{{_P&J@fPVV2ELnm^%d%*=L=C0k;IUJJfF$p7xk_T8;{ z?5&qR^3`zcxcKNoj_s?1x25)r%G59Av2~epH+{kOBh%FiAJtt<>Yj1<)UmG3mJF|W z3j&;#e=T4$eDYCEM!4@p^|7z+Wnn4pZ=B`+bDIhs zp272;Y;n*2 z{OG1NpCiA|f7$s7FOOf4TN2r3^2Gk%3L)nw3;WMV&Aw5swezu!b8fc&Qdu$ATh=W1 z9_H;>oVn&L+Z^jlyk{;Yue#b^`%opU3=oSpr%~ki<~5JQji;JxWPB4V%(6NB`TUQo#$ArQu`m89 zeQ3(G-2NtTYo5ba*_RpZDk}wZJ=J^VoEE!V?K14W$R8;8a>8Ggw;PMvJUr#@EjVVf zB9ZR_^M2{uAKa|JCcG~{Wm5rX_ww!QeeOTV*8nj z4)0si4<@UW7_dKEJVDoK50hrcAq^$2os;Tr?Rc+z@O$F?qcc0Sx_ah2>Rxu*Io-p) zEuv>r&_T99&dIwc{lCDIa9F6NfT!+&%9=$2-<^5Z-fDko&GE;oLv@Ra&c`)+H`o99 zwWdt_pq5I$u!s(4S++p>L(}xgX;slO(kd%dpQv=KP-;D)!WihRZ0-D~NT9xB{@Dz3 zlb3edTMm~OJKH@LGJJA)O}3$!%7hiW4?C(HaWXmL>~h2<Q%P5$_{Me6AeveR9N4XL17rgEatT*T~8M literal 0 HcmV?d00001 diff --git a/doc/comp.sh b/doc/comp.sh new file mode 100644 index 0000000..a46a568 --- /dev/null +++ b/doc/comp.sh @@ -0,0 +1,6 @@ +sh comp_ptr_container.sh +sh comp_reversible_ptr_container.sh +sh comp_ptr_sequence_adapter.sh +sh comp_associative_ptr_container.sh +sh comp_ptr_set_adapter.sh + diff --git a/doc/comp_all.sh b/doc/comp_all.sh new file mode 100644 index 0000000..45d27c8 --- /dev/null +++ b/doc/comp_all.sh @@ -0,0 +1,26 @@ +sh comp_ptr_container.sh +sh comp_reference.sh +sh comp_faq.sh +sh comp_tutorial.sh +sh comp_guidelines.sh +sh comp_headers.sh +sh comp_examples.sh +sh comp_conventions.sh +sh comp_reversible_ptr_container.sh +sh comp_ptr_sequence_adapter.sh +sh comp_associative_ptr_container.sh +sh comp_ptr_set_adapter.sh +sh comp_ptr_multiset_adapter.sh +sh comp_ptr_map_adapter.sh +sh comp_ptr_multimap_adapter.sh +sh comp_ptr_array.sh +sh comp_ptr_vector.sh +sh comp_ptr_deque.sh +sh comp_ptr_list.sh +sh comp_ptr_map.sh +sh comp_ptr_multimap.sh +sh comp_ptr_set.sh +sh comp_ptr_multiset.sh +sh comp_indirect_fun.sh + + diff --git a/doc/comp_associative_ptr_container.sh b/doc/comp_associative_ptr_container.sh new file mode 100644 index 0000000..a76f235 --- /dev/null +++ b/doc/comp_associative_ptr_container.sh @@ -0,0 +1,2 @@ +rst2html.py associative_ptr_container.rst > associative_ptr_container.html + diff --git a/doc/comp_conventions.sh b/doc/comp_conventions.sh new file mode 100644 index 0000000..615bff1 --- /dev/null +++ b/doc/comp_conventions.sh @@ -0,0 +1 @@ +rst2html.py conventions.rst > conventions.html diff --git a/doc/comp_examples.sh b/doc/comp_examples.sh new file mode 100644 index 0000000..be8691b --- /dev/null +++ b/doc/comp_examples.sh @@ -0,0 +1,2 @@ +rst2html.py examples.rst > examples.html + diff --git a/doc/comp_faq.sh b/doc/comp_faq.sh new file mode 100644 index 0000000..56a3d7c --- /dev/null +++ b/doc/comp_faq.sh @@ -0,0 +1,2 @@ +rst2html.py faq.rst > faq.html + diff --git a/doc/comp_guidelines.sh b/doc/comp_guidelines.sh new file mode 100644 index 0000000..4ac1399 --- /dev/null +++ b/doc/comp_guidelines.sh @@ -0,0 +1,2 @@ +rst2html.py guidelines.rst > guidelines.html + diff --git a/doc/comp_headers.sh b/doc/comp_headers.sh new file mode 100644 index 0000000..19db5c1 --- /dev/null +++ b/doc/comp_headers.sh @@ -0,0 +1,2 @@ +rst2html.py headers.rst > headers.html + diff --git a/doc/comp_indirect_fun.sh b/doc/comp_indirect_fun.sh new file mode 100644 index 0000000..0e5ec3f --- /dev/null +++ b/doc/comp_indirect_fun.sh @@ -0,0 +1,2 @@ +rst2html.py indirect_fun.rst > indirect_fun.html + diff --git a/doc/comp_ptr_array.sh b/doc/comp_ptr_array.sh new file mode 100644 index 0000000..565ba39 --- /dev/null +++ b/doc/comp_ptr_array.sh @@ -0,0 +1,2 @@ +rst2html.py ptr_array.rst > ptr_array.html + diff --git a/doc/comp_ptr_container.sh b/doc/comp_ptr_container.sh new file mode 100644 index 0000000..09e2445 --- /dev/null +++ b/doc/comp_ptr_container.sh @@ -0,0 +1,2 @@ +rst2html.py ptr_container.rst > ptr_container.html + diff --git a/doc/comp_ptr_deque.sh b/doc/comp_ptr_deque.sh new file mode 100644 index 0000000..d11628f --- /dev/null +++ b/doc/comp_ptr_deque.sh @@ -0,0 +1,2 @@ +rst2html.py ptr_deque.rst > ptr_deque.html + diff --git a/doc/comp_ptr_list.sh b/doc/comp_ptr_list.sh new file mode 100644 index 0000000..adc7712 --- /dev/null +++ b/doc/comp_ptr_list.sh @@ -0,0 +1,2 @@ +rst2html.py ptr_list.rst > ptr_list.html + diff --git a/doc/comp_ptr_map.sh b/doc/comp_ptr_map.sh new file mode 100644 index 0000000..368b12a --- /dev/null +++ b/doc/comp_ptr_map.sh @@ -0,0 +1,2 @@ +rst2html.py ptr_map.rst > ptr_map.html + diff --git a/doc/comp_ptr_map_adapter.sh b/doc/comp_ptr_map_adapter.sh new file mode 100644 index 0000000..4d15e09 --- /dev/null +++ b/doc/comp_ptr_map_adapter.sh @@ -0,0 +1,2 @@ +rst2html.py ptr_map_adapter.rst > ptr_map_adapter.html + diff --git a/doc/comp_ptr_multimap.sh b/doc/comp_ptr_multimap.sh new file mode 100644 index 0000000..f9a24c9 --- /dev/null +++ b/doc/comp_ptr_multimap.sh @@ -0,0 +1,2 @@ +rst2html.py ptr_multimap.rst > ptr_multimap.html + diff --git a/doc/comp_ptr_multimap_adapter.sh b/doc/comp_ptr_multimap_adapter.sh new file mode 100644 index 0000000..045e8de --- /dev/null +++ b/doc/comp_ptr_multimap_adapter.sh @@ -0,0 +1,2 @@ +rst2html.py ptr_multimap_adapter.rst > ptr_multimap_adapter.html + diff --git a/doc/comp_ptr_multiset.sh b/doc/comp_ptr_multiset.sh new file mode 100644 index 0000000..e3bf931 --- /dev/null +++ b/doc/comp_ptr_multiset.sh @@ -0,0 +1,2 @@ +rst2html.py ptr_multiset.rst > ptr_multiset.html + diff --git a/doc/comp_ptr_multiset_adapter.sh b/doc/comp_ptr_multiset_adapter.sh new file mode 100644 index 0000000..69f6dee --- /dev/null +++ b/doc/comp_ptr_multiset_adapter.sh @@ -0,0 +1,2 @@ +rst2html.py ptr_multiset_adapter.rst > ptr_multiset_adapter.html + diff --git a/doc/comp_ptr_sequence_adapter.sh b/doc/comp_ptr_sequence_adapter.sh new file mode 100644 index 0000000..7a520e4 --- /dev/null +++ b/doc/comp_ptr_sequence_adapter.sh @@ -0,0 +1,2 @@ +rst2html.py ptr_sequence_adapter.rst > ptr_sequence_adapter.html + diff --git a/doc/comp_ptr_set.sh b/doc/comp_ptr_set.sh new file mode 100644 index 0000000..7c5c54f --- /dev/null +++ b/doc/comp_ptr_set.sh @@ -0,0 +1,2 @@ +rst2html.py ptr_set.rst > ptr_set.html + diff --git a/doc/comp_ptr_set_adapter.sh b/doc/comp_ptr_set_adapter.sh new file mode 100644 index 0000000..5143422 --- /dev/null +++ b/doc/comp_ptr_set_adapter.sh @@ -0,0 +1,2 @@ +rst2html.py ptr_set_adapter.rst > ptr_set_adapter.html + diff --git a/doc/comp_ptr_vector.sh b/doc/comp_ptr_vector.sh new file mode 100644 index 0000000..0675886 --- /dev/null +++ b/doc/comp_ptr_vector.sh @@ -0,0 +1,2 @@ +rst2html.py ptr_vector.rst > ptr_vector.html + diff --git a/doc/comp_reference.sh b/doc/comp_reference.sh new file mode 100644 index 0000000..70538c5 --- /dev/null +++ b/doc/comp_reference.sh @@ -0,0 +1 @@ +rst2html.py reference.rst > reference.html diff --git a/doc/comp_reversible_ptr_container.sh b/doc/comp_reversible_ptr_container.sh new file mode 100644 index 0000000..cc62bad --- /dev/null +++ b/doc/comp_reversible_ptr_container.sh @@ -0,0 +1,2 @@ +rst2html.py reversible_ptr_container.rst > reversible_ptr_container.html + diff --git a/doc/comp_tutorial.sh b/doc/comp_tutorial.sh new file mode 100644 index 0000000..b1a0019 --- /dev/null +++ b/doc/comp_tutorial.sh @@ -0,0 +1,2 @@ +rst2html.py tutorial.rst > tutorial.html + diff --git a/doc/conventions.html b/doc/conventions.html new file mode 100644 index 0000000..147eb52 --- /dev/null +++ b/doc/conventions.html @@ -0,0 +1,114 @@ + + + + + + +Conventions + + + +
+

Conventions

+

There are a few design decisions that will affect how the classes are +used. Besides these the classes are much like normal standard containers +and provides almost the same interface. The new conventions are:

+ +
+

Null pointers are not allowed by default

+

If the user tries to insert the null pointer, the operation will throw a +bad_pointer exception (see Example 1).

+

Use nullable to allow null pointers.

+

Please notice that all preconditions of the form

+
+x != 0;
+
+

are not active when the you have instantiated a container +with nullable<T> as in

+
+boost::ptr_vector< boost::nullable<animal> > vec;
+vec.push_back( 0 ); // ok
+
+
+
+

All default iterators apply an extra layer of indirection

+

This is done to +make the containers easier and safer to use. It promotes a kind of +pointer-less programming and the user of a class needs not worry about +pointers except when allocating them (see Example 2). Iterators that +provide access to the naked pointers are also provided since they might be +useful in rare cases. For example, whenever begin() returns an iterator, +ptr_begin() will return an iterator that allows one to iterate over the +stored pointers.

+
+
+

All comparison operations are done on the pointed to objects and not at the pointer level

+

For example, in ptr_set<T> the ordering is by default done by +boost::ptr_less<T> which compares the indirected pointers. +Similarly, operator==() for container<Foo> compares all objects +with operator==(const Foo&, const Foo&).

+
+
+

The containers are neither Copy Constructible nor Assignable

+

This is +because cloning a lot of pointers can be a very expensive operation; +instead functions are provided to transfer ownership. If a deep-copy is +needed anyway, every container has a clone() member function +(see Example 3).

+
+
+

Stored elements are required to be Clonable for a subset of the operations

+

This is because most polymorphic objects cannot be copied directly, but +they can often be so by a use of a member function (see Example 4). Often +it does not even make sense to clone an object in which case a large +subset of the operations are still workable.

+
+
+

Whenever objects are inserted into a container, they are cloned before insertion

+

This is necessary because all pointer containers take ownerships of stored objects +(see Example 5).

+
+
+

Whenever pointers are inserted into a container, ownership is transferred to the container

+

All containers take ownership of the stored pointers and therefore a +container needs to have its own copies (see Example 5).

+
+
+

Ownership can be transferred from a container on a per pointer basis

+

This can of course also be convenient. Whenever it happens, an +SmartContainer::auto_type object is used to provide an exception-safe transfer +(see Example 6).

+
+
+

Ownership can be transferred from a container to another container on a per iterator range basis

+

This makes it possible to exchange data safely between different pointer +containers without cloning the objects again (see Example 7).

+
+
+

A container can be cheaply returned from functions either by making a clone or by giving up ownership of the container

+

Two special member functions, clone() and release(), both return an +auto_ptr<SmartContainer> which can be assigned to another pointer container. This +effectively reduces the cost of returning a container to one +heap-allocation plus a call to swap() (see Example 3).

+

Navigate:

+ +
+
+ + diff --git a/doc/conventions.rst b/doc/conventions.rst new file mode 100755 index 0000000..4f94163 --- /dev/null +++ b/doc/conventions.rst @@ -0,0 +1,102 @@ +Conventions ++++++++++++ + +There are a few design decisions that will affect how the classes are +used. Besides these the classes are much like normal standard containers +and provides almost the same interface. The new conventions are: + +.. contents:: :local: + +Null pointers are not allowed by default +---------------------------------------- + +If the user tries to insert the null pointer, the operation will throw a +``bad_pointer`` exception (see `Example 1 `_). + +Use `nullable `_ to allow null pointers. + +Please notice that all preconditions of the form :: + + x != 0; + +are not active when the you have instantiated a container +with ``nullable`` as in :: + + boost::ptr_vector< boost::nullable > vec; + vec.push_back( 0 ); // ok + +All default iterators apply an extra layer of indirection +--------------------------------------------------------- + +This is done to +make the containers easier and safer to use. It promotes a kind of +pointer-less programming and the user of a class needs not worry about +pointers except when allocating them (see `Example 2 `_). Iterators that +provide access to the naked pointers are also provided since they might be +useful in rare cases. For example, whenever ``begin()`` returns an iterator, +``ptr_begin()`` will return an iterator that allows one to iterate over the +stored pointers. + +All comparison operations are done on the pointed to objects and not at the pointer level +----------------------------------------------------------------------------------------- + +For example, in ``ptr_set`` the ordering is by default done by +``boost::ptr_less`` which compares the indirected pointers. +Similarly, ``operator==()`` for ``container`` compares all objects +with ``operator==(const Foo&, const Foo&)``. + +The containers are neither Copy Constructible nor Assignable +------------------------------------------------------------ + +This is +because cloning a lot of pointers can be a very expensive operation; +instead functions are provided to transfer ownership. If a deep-copy is +needed anyway, every container has a ``clone()`` member function +(see `Example 3 `_). + +Stored elements are required to be `Clonable `_ for a subset of the operations +------------------------------------------------------------------------------------------------------------------- + +This is because most polymorphic objects cannot be copied directly, but +they can often be so by a use of a member function (see `Example 4 `_). Often +it does not even make sense to clone an object in which case a large +subset of the operations are still workable. + +Whenever objects are inserted into a container, they are cloned before insertion +-------------------------------------------------------------------------------- + +This is necessary because all pointer containers take ownerships of stored objects +(see `Example 5 `_). + +Whenever pointers are inserted into a container, ownership is transferred to the container +------------------------------------------------------------------------------------------ + +All containers take ownership of the stored pointers and therefore a +container needs to have its own copies (see `Example 5 `_). + +Ownership can be transferred from a container on a per pointer basis +-------------------------------------------------------------------- + +This can of course also be convenient. Whenever it happens, an +``SmartContainer::auto_type`` object is used to provide an exception-safe transfer +(see `Example 6 `_). + +Ownership can be transferred from a container to another container on a per iterator range basis +------------------------------------------------------------------------------------------------ + +This makes it possible to exchange data safely between different pointer +containers without cloning the objects again (see `Example 7 `_). + +A container can be cheaply returned from functions either by making a clone or by giving up ownership of the container +---------------------------------------------------------------------------------------------------------------------- + +Two special member functions, ``clone()`` and ``release()``, both return an +``auto_ptr`` which can be assigned to another pointer container. This +effectively reduces the cost of returning a container to one +heap-allocation plus a call to ``swap()`` (see `Example 3 `_). + +**Navigate:** + +- `home `_ +- `reference `_ + diff --git a/doc/default.css b/doc/default.css new file mode 100755 index 0000000..bb45e79 --- /dev/null +++ b/doc/default.css @@ -0,0 +1,248 @@ +/* +:Author: David Goodger +:Contact: goodger@users.sourceforge.net +:date: $Date$ +:version: $Revision$ +:copyright: This stylesheet has been placed in the public domain. + +Default cascading style sheet for the HTML output of Docutils. +*/ + +.first { + margin-top: 0 } + +.last { + margin-bottom: 0 } + +a.toc-backref { + text-decoration: none ; + color: black } + +dd { + margin-bottom: 0.5em } + +div.abstract { + margin: 2em 5em } + +div.abstract p.topic-title { + font-weight: bold ; + text-align: center } + +div.attention, div.caution, div.danger, div.error, div.hint, +div.important, div.note, div.tip, div.warning, div.admonition { + margin: 2em ; + border: medium outset ; + padding: 1em } + +div.attention p.admonition-title, div.caution p.admonition-title, +div.danger p.admonition-title, div.error p.admonition-title, +div.warning p.admonition-title { + color: red ; + font-weight: bold ; + font-family: sans-serif } + +div.hint p.admonition-title, div.important p.admonition-title, +div.note p.admonition-title, div.tip p.admonition-title, +div.admonition p.admonition-title { + font-weight: bold ; + font-family: sans-serif } + +div.dedication { + margin: 2em 5em ; + text-align: center ; + font-style: italic } + +div.dedication p.topic-title { + font-weight: bold ; + font-style: normal } + +div.figure { + margin-left: 2em } + +div.footer, div.header { + font-size: smaller } + +div.sidebar { + margin-left: 1em ; + border: medium outset ; + padding: 0em 1em ; + background-color: #ffffee ; + width: 40% ; + float: right ; + clear: right } + +div.sidebar p.rubric { + font-family: sans-serif ; + font-size: medium } + +div.system-messages { + margin: 5em } + +div.system-messages h1 { + color: red } + +div.system-message { + border: medium outset ; + padding: 1em } + +div.system-message p.system-message-title { + color: red ; + font-weight: bold } + +div.topic { + margin: 2em } + +h1.title { + text-align: center } + +h2.subtitle { + text-align: center } + +hr { + width: 75% } + +ol.simple, ul.simple { + margin-bottom: 1em } + +ol.arabic { + list-style: decimal } + +ol.loweralpha { + list-style: lower-alpha } + +ol.upperalpha { + list-style: upper-alpha } + +ol.lowerroman { + list-style: lower-roman } + +ol.upperroman { + list-style: upper-roman } + +p.attribution { + text-align: right ; + margin-left: 50% } + +p.caption { + font-style: italic } + +p.credits { + font-style: italic ; + font-size: smaller } + +p.label { + white-space: nowrap } + +p.rubric { + font-weight: bold ; + font-size: larger ; + color: maroon ; + text-align: center } + +p.sidebar-title { + font-family: sans-serif ; + font-weight: bold ; + font-size: larger } + +p.sidebar-subtitle { + font-family: sans-serif ; + font-weight: bold } + +p.topic-title { + font-weight: bold } + +pre.address { + margin-bottom: 0 ; + margin-top: 0 ; + font-family: serif ; + font-size: 100% } + +pre.line-block { + font-family: serif ; + font-size: 100% } + +pre.literal-block, pre.doctest-block { + margin-left: 2em ; + margin-right: 2em ; + background-color: #eeeeee } + +span.classifier { + font-family: sans-serif ; + font-style: oblique } + +span.classifier-delimiter { + font-family: sans-serif ; + font-weight: bold } + +span.interpreted { + font-family: sans-serif } + +span.option { + white-space: nowrap } + +span.option-argument { + font-style: italic } + +span.pre { + white-space: pre } + +span.problematic { + color: red } + +table { + margin-top: 0.5em ; + margin-bottom: 0.5em } + +table.citation { + border-left: solid thin gray ; + padding-left: 0.5ex } + +table.docinfo { + margin: 2em 4em } + +table.footnote { + border-left: solid thin black ; + padding-left: 0.5ex } + +td, th { + padding-left: 0.5em ; + padding-right: 0.5em ; + vertical-align: top } + +th.docinfo-name, th.field-name { + font-weight: bold ; + text-align: left ; + white-space: nowrap } + +h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { + font-size: 100% } + +tt { + background-color: #eeeeee } + +ul.auto-toc { + list-style-type: none } + +pre{ + BORDER-RIGHT: gray 1pt solid; + PADDING-RIGHT: 2pt; + BORDER-TOP: gray 1pt solid; + DISPLAY: block; + PADDING-LEFT: 2pt; + PADDING-BOTTOM: 2pt; + BORDER-LEFT: gray 1pt solid; + MARGIN-RIGHT: 32pt; + PADDING-TOP: 2pt; + BORDER-BOTTOM: gray 1pt solid; + FONT-FAMILY: "Courier New", Courier, mono; + background-color: #EEEEEE; +} + + +.keyword{color: #0000FF;} +.identifier{} +.comment{font-style: italic; color: #008000;} +.special{color: #800040;} +.preprocessor{color: #3F007F;} +.string{font-style: italic; color: #666666;} +.literal{/*font-style: italic;*/ color: #000000;} diff --git a/doc/examples.html b/doc/examples.html new file mode 100644 index 0000000..2136caa --- /dev/null +++ b/doc/examples.html @@ -0,0 +1,689 @@ + + + + + + +Examples + + + +
+

Examples

+

Some examples are given here and in the accompanying test files:

+ +
+

1. Null pointers cannot be stored in the containers

+
+my_container.push_back( 0 );            // throws bad_ptr 
+my_container.replace( an_iterator, 0 ); // throws bad_ptr
+my_container.insert( an_iterator, 0 );  // throws bad_ptr                                                                 
+
+
+
+

2. Iterators and other operations return indirected values

+
+ptr_vector<X> pvec; 
+std::vector<X*> vec;
+*vec.begin()  = new X;   // fine, memory leak
+*pvec.begin() = new X;   // compile time error
+( *vec.begin() )->foo(); // call X::foo(), a bit clumsy
+pvec.begin()->foo();     // no indirection needed
+*vec.front()  = X();     // overwrite first element
+pvec.front()  = X();     // no indirection needed
+
+
+
+

3. Copy-semantics of pointer containers

+
+ptr_vector<T> vec1; 
+...
+ptr_vector<T> vec2( vec1.clone() ); // deep copy objects of 'vec1' and use them to construct 'vec2', could be very expensive
+vec2 = vec1.release();              // give up ownership of pointers in 'vec1' and pass the ownership to 'vec2', rather cheap
+vec2.release();                     // give up ownership; the objects will be deallocated if not assigned to another container
+vec1 = vec2;                        // compile time error: 'operator=()' not defined 
+ptr_vector<T> vec3( vec1 );         // compile time error: copy-constructor not defined 
+
+
+
+

4. Making a non-copyable type Clonable

+
+ // a class that has no normal copy semantics
+class X : boost::noncopyable { public: X* clone() const; ... };
+                                                                   
+// this will be found by the library by argument dependent lookup                                                                   
+X* allocate_clone( const X& x ) 
+{ return x.clone(); }
+                                                                   
+// we can now use the interface that requires clonability
+ptr_vector<X> vec1, vec2;
+...
+vec2 = vec1.clone();                                 // 'clone()' requires cloning <g> 
+vec2.insert( vec2.end(), vec1.begin(), vec1.end() ); // inserting always means inserting clones 
+
+
+
+

5. Objects are cloned before insertion, inserted pointers are owned by the container

+
+class X { ... };                     // assume 'X' is Clonable 
+X x;                                 // and 'X' can be stack-allocated 
+ptr_list<X> list; 
+list.push_back( x );                 // clone 'x' and then insert the resulting pointer 
+list.push_back( allocate_clone( x ); // do it manually
+list.push_back( new X );             // always give the pointer directly to the container to avoid leaks
+list.push_back( &x );                // don't do this!!! 
+
+
+
+

6. Transferring ownership of a single element

+
+ptr_deque<T>                    deq; 
+typedef ptr_deque<T>::auto_type auto_type;
+
+// ... fill the container somehow
+
+auto_type ptr  = deq.release_back();             // remove back element from container and give up ownership
+auto_type ptr2 = deq.release( deq.begin() + 2 ); // use an iterator to determine the element to release
+ptr            = deq.release_front();            // supported for 'ptr_list' and 'ptr_deque'
+
+
+
+

7. Transferring ownership of pointers between different pointer containers

+
+ptr_list<X> list; ptr_vector<X> vec;
+...
+//
+// note: no cloning happens in these examples                                
+//
+list.transfer( list.begin(), vec.begin(), vec );           // make the first element of 'vec' the first element of 'list'
+vec.transfer( vec.end(), list.begin(), list.end(), list ); // put all the lists element into the vector                                 
+
+
+
+

8. Selected test files

+ +++ + + + + + + + + + + + + + + +
incomplete_type_test.cpp:
 Shows how to implement the Composite pattern.
simple_test.cpp:
 Shows how the usage of pointer container compares with a +container of pointer pointers
view_example.cpp:
 Shows how to use a pointer container as a view into other container
tree_test.cpp:Shows how to make a tree-structure
array_test.cpp:Shows how to make an n-ary tree
+
+
+

9. A large example

+

This examples shows many of the most common +features at work.

+ + + + + + + + + + +
+//
+// This example is intended to get you started.
+// Notice how the smart container
+//
+// 1. takes ownership of objects
+// 2. transfers ownership
+// 3. applies indirection to iterators 
+// 4. clones objects from other smart containers
+// 
+
+//
+// First we select which container to use.
+//
+#include <boost/smart_container/ptr_deque.hpp>
+
+//
+// we need these later in the example
+//
+#include <boost/assert.hpp>
+#include <string>
+#include <exception>
+
+
+//
+// Then we define a small polymorphic class
+// hierarchy.
+// 
+
+class animal
+{
+    virtual std::string do_speak() const = 0;
+    std::string name_;
+
+protected:
+    //
+    // Animals cannot be copied...
+    //
+    animal( const animal& r ) : name_( r.name_ )           { }
+    void operator=( const animal& );
+
+private:
+    //
+    // ...but due to advances in genetics, we can clone them!
+    //
+
+    virtual animal* do_clone() const = 0;
+        
+public:
+    animal( const std::string& name ) : name_(name)        { }
+    virtual ~animal() throw()                              { }
+    
+    std::string speak() const
+    {
+        return do_speak();
+    }
+
+    std::string name() const
+    {
+        return name_;
+    }
+
+    animal* clone() const
+    {
+        return do_clone();
+    }
+};
+
+//
+// An animal is still not Clonable. We need this last hook.
+//
+// Notice that we pass the animal by const reference
+// and return by pointer.
+//
+
+animal* allocate_clone( const animal& a )
+{
+    return a.clone();
+}
+
+//
+// We do not need to define 'delete_clone()' since
+// since the default is to call the default 'operator delete()'.
+//
+
+const std::string muuuh = "Muuuh!";
+const std::string oiink = "Oiiink";
+
+class cow : public animal
+{
+    virtual std::string do_speak() const
+    {
+        return muuuh;
+    }
+
+    virtual animal* do_clone() const
+    {
+        return new cow( *this );
+    }
+
+public:
+    cow( const std::string& name ) : animal(name)          { }
+};
+
+class pig : public animal
+{
+    virtual std::string do_speak() const
+    {
+        return oiink;
+    }
+
+    virtual animal* do_clone() const
+    {
+        return new pig( *this );
+    }
+    
+public:
+    pig( const std::string& name ) : animal(name)          { }
+};
+
+//
+// Then we, of course, need a place to put all
+// those animals.
+//
+
+class farm
+{
+    //
+    // This is where the smart containers are handy
+    //
+    typedef boost::ptr_deque<animal> barn_type;
+    barn_type                      barn;
+
+    //
+    // An error type
+    //
+    struct farm_trouble : public std::exception           { };
+
+public:
+    // 
+    // We would like to make it possible to
+    // iterate over the animals in the farm
+    //
+    typedef barn_type::iterator  animal_iterator;
+
+    //
+    // We also need to count the farm's size...
+    //
+    typedef barn_type::size_type size_type;
+    
+    //
+    // And we also want to transfer an animal
+    // safely around. The easiest way to think
+    // about '::auto_type' is to imagine a simplified
+    // 'std::auto_ptr<T>' ... this means you can expect
+    // 
+    //   T* operator->()
+    //   T* release()
+    //   deleting destructor
+    //
+    // but not more.
+    //
+    typedef barn_type::auto_type  animal_transport;
+
+    // 
+    // Create an empty farm.
+    //
+    farm()                                                 { }
+    
+    //
+    // We need a constructor that can make a new
+    // farm by cloning a range of animals.
+    //
+    farm( animal_iterator begin, animal_iterator end )
+     : 
+        //
+        // Objects are always cloned before insertion
+        // unless we explicitly add a pointer or 
+        // use 'release()'. Therefore we actually
+        // clone all animals in the range
+        //
+        barn( begin, end )                               { }
+    
+    //
+    // ... so we need some other function too
+    //
+
+    animal_iterator begin()
+    {
+        return barn.begin();
+    }
+
+    animal_iterator end()
+    {
+        return barn.end();
+    }
+    
+    //
+    // Here it is quite ok to have an 'animal*' argument.
+    // The smart container will handle all ownership
+    // issues.
+    //
+    void buy_animal( animal* a )
+    {
+        barn.push_back( a );
+    }
+
+    //
+    // The farm can also be in economical trouble and
+    // therefore be in the need to sell animals.
+    //
+    animal_transport sell_animal( animal_iterator to_sell )
+    {
+        if( to_sell == end() )
+            throw farm_trouble();
+
+        //
+        // Here we remove the animal from the barn,
+        // but the animal is not deleted yet...it's
+        // up to the buyer to decide what
+        // to do with it.
+        //
+        return barn.release( to_sell );
+    }
+
+    //
+    // How big a farm do we have?
+    //
+    size_type size() const
+    {
+        return barn.size();
+    }
+
+    //
+    // If things are bad, we might choose to sell all animals :-(
+    //
+    std::auto_ptr<barn_type> sell_farm()
+    {
+        return barn.release();
+    }
+
+    //
+    // However, if things are good, we might buy somebody
+    // else's farm :-)
+    //
+
+    void buy_farm( std::auto_ptr<barn_type> other )
+    {
+        //
+        // This line inserts all the animals from 'other'
+        // and is guaranteed either to succeed or to have no
+        // effect
+        //
+        barn.transfer( barn.end(), // insert new animals at the end
+                         *other );     // we want to transfer all animals,
+                                       // so we use the whole container as argument
+        //
+        // You might think you would have to do
+        //
+        // other.release();
+        //
+        // but '*other' is empty and can go out of scope as it wants
+        //
+        BOOST_ASSERT( other->empty() );
+    }
+    
+}; // class 'farm'.
+
+int main()
+{
+    //
+    // First we make a farm
+    //
+    farm animal_farm;
+    BOOST_ASSERT( animal_farm.size() == 0u );
+    
+    animal_farm.buy_animal( new pig("Betty") );
+    animal_farm.buy_animal( new pig("Benny") );
+    animal_farm.buy_animal( new pig("Jeltzin") );
+    animal_farm.buy_animal( new cow("Hanz") );
+    animal_farm.buy_animal( new cow("Mary") );
+    animal_farm.buy_animal( new cow("Frederik") );
+    BOOST_ASSERT( animal_farm.size() == 6u );
+
+    //
+    // Then we make another farm...it will actually contain
+    // a clone of the other farm.
+    //
+    farm new_farm( animal_farm.begin(), animal_farm.end() );
+    BOOST_ASSERT( new_farm.size() == 6u );
+
+    //
+    // Is it really clones in the new farm?
+    //
+    BOOST_ASSERT( new_farm.begin()->name() == "Betty" );
+    
+    //
+    // Then we search for an animal, Mary (the Crown Princess of Denmark),
+    // because we would like to buy her ...
+    //
+    typedef farm::animal_iterator iterator;
+    iterator to_sell;
+    for( iterator i   = animal_farm.begin(),
+                  end = animal_farm.end();
+         i != end; ++i )
+    {
+        if( i->name() == "Mary" )
+        {
+            to_sell = i;
+            break;
+        }
+    }
+
+    farm::animal_transport mary = animal_farm.sell_animal( to_sell );
+
+
+    if( mary->speak() == muuuh )
+        //
+        // Great, Mary is a cow, and she may live longer
+        //
+        new_farm.buy_animal( mary.release() );
+    else
+        //
+        // Then the animal would be destroyed (!)
+        // when we go out of scope.
+        //
+        ;
+
+    //
+    // Now we can observe some changes to the two farms...
+    //
+    BOOST_ASSERT( animal_farm.size() == 5u );
+    BOOST_ASSERT( new_farm.size()    == 7u );
+
+    //
+    // The new farm has however underestimated how much
+    // it cost to feed Mary and its owner is forced to sell the farm...
+    //
+    animal_farm.buy_farm( new_farm.sell_farm() );
+
+    BOOST_ASSERT( new_farm.size()    == 0u );
+    BOOST_ASSERT( animal_farm.size() == 12u );     
+}
+
+ + + +
+
+

10. Changing the Clone Allocator

+

This example shows how we can change +the Clone Allocator to use the pointer containers +as view into other containers:

+ + + + + + + + + + +
+//
+// This example is intended to show you how to
+// use the 'view_clone_manager'. The idea
+// is that we have a container of non-polymorphic
+// objects and want to keep then sorted by different
+// criteria at the same time. 
+//
+
+//
+// We'll go for 'ptr_vector' here. Using a node-based 
+// container would be a waste of space here.
+// All container headers will also include
+// the Clone Managers.
+// 
+#include <boost/smart_container/ptr_vector.hpp>
+#include <boost/smart_container/ptr_predicate.hpp>
+
+#include <cstdlib>   // For 'rand()'
+#include <algorithm> // For 'std::sort()'
+#include <iostream>  // For 'std::cout'
+
+
+//
+// This is our simple example data-structure. It can
+// be ordered in three ways.
+//
+struct photon
+{
+    photon() : color( std::rand() ), 
+               direction( std::rand() ),
+               power( std::rand() )
+    { }
+    
+    int color;
+    int direction;
+    int power;
+};
+
+//
+// Our big container is a standard vector
+//
+typedef std::vector<photon>                                 vector_type;
+
+//
+// Now we define our view type by adding a second template argument.
+// The 'view_clone_manager' will implements Cloning by taking address
+// of objects.
+//
+// Notice the first template argument is 'photon' and not
+// 'const photon' to allow the view container write access.
+//
+typedef boost::ptr_vector<photon,boost::view_clone_manager> view_type;
+
+//
+// Our first sort criterium
+//
+struct sort_by_color
+{
+    bool operator()( const photon& l, const photon& r ) const
+    {
+        return l.color < r.color;
+    }
+};
+
+//
+// Our second sort criterium
+//
+struct sort_by_direction
+{
+    bool operator()( const photon& l, const photon& r ) const
+    {
+        return l.direction < r.direction;
+    }
+};
+
+
+//
+// Our third sort criterium
+//
+struct sort_by_power
+{
+    bool operator()( const photon& l, const photon& r ) const
+    {
+        return l.power < r.power;
+    }
+};
+
+//
+// This function inserts "Clones" into the
+// the view. 
+//
+// We need to pass the first argument
+// as a non-const reference to be able to store
+// 'T*' instead of 'const T*' objects. Alternatively,
+// we might change the declaration of the 'view_type'
+// to 
+//     typedef boost::ptr_vector<const photon,boost::view_clone_manager> 
+//               view_type;     ^^^^^^
+//
+void insert( vector_type& from, view_type& to )
+{
+        to.insert( to.end(), 
+                   from.begin(),
+                   from.end() );
+}
+
+int main()
+{
+    enum { sz = 10, count = 500 };
+
+    //
+    // First we create the main container and two views
+    //
+    std::vector<vector_type>  photons;
+    view_type                 color_view;
+    view_type                 direction_view;
+
+    //
+    // Then we fill the main container with some random data
+    //
+    for( int i = 0; i != sz; ++i )
+    {
+        photons.push_back( vector_type() ); 
+
+        for( int j = 0; j != count; ++j )
+            photons[i].push_back( photon() );
+    }
+
+    //
+    // Then we create the two views.
+    //
+    for( int i = 0; i != sz; ++i )
+    {
+        insert( photons[i], color_view );
+        insert( photons[i], direction_view );
+    }
+
+    //
+    // First we sort the original photons, using one of
+    // the view classes. This may sound trivial, but consider that
+    // the objects are scatered all around 'sz' different vectors;
+    // the view makes them act as one big vector.
+    //
+    // Notice how we simple use
+    // '.begin()/end()' instead of '.ptr_begin()/ptr_end()':
+    //
+    std::sort( color_view.begin(), color_view.end(), sort_by_power() );
+    
+    //
+    // And now we can sort the views themselves. Notice how
+    // we switch to different iterators and different predicates:
+    //
+    std::sort( color_view.ptr_begin(), color_view.ptr_end(),
+               boost::indirected2<sort_by_color>() );
+
+    std::sort( direction_view.ptr_begin(), direction_view.ptr_end(),
+               boost::indirected2<sort_by_direction>() );
+
+    return 0;
+}
+
+
+ + + +

Navigate:

+ +
+
+ + diff --git a/doc/examples.rst b/doc/examples.rst new file mode 100755 index 0000000..e8c1c90 --- /dev/null +++ b/doc/examples.rst @@ -0,0 +1,170 @@ +======== +Examples +======== + +Some examples are given here and in the accompanying test files: + +.. contents:: :local: + + +.. _`Example 1`: + +1. Null pointers cannot be stored in the containers ++++++++++++++++++++++++++++++++++++++++++++++++++++ + +:: + + my_container.push_back( 0 ); // throws bad_ptr + my_container.replace( an_iterator, 0 ); // throws bad_ptr + my_container.insert( an_iterator, 0 ); // throws bad_ptr + +.. _`Example 2`: + +2. Iterators and other operations return indirected values +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +:: + + ptr_vector pvec; + std::vector vec; + *vec.begin() = new X; // fine, memory leak + *pvec.begin() = new X; // compile time error + ( *vec.begin() )->foo(); // call X::foo(), a bit clumsy + pvec.begin()->foo(); // no indirection needed + *vec.front() = X(); // overwrite first element + pvec.front() = X(); // no indirection needed + + +.. _`Example 3`: + +3. Copy-semantics of pointer containers ++++++++++++++++++++++++++++++++++++++++ + +:: + + ptr_vector vec1; + ... + ptr_vector vec2( vec1.clone() ); // deep copy objects of 'vec1' and use them to construct 'vec2', could be very expensive + vec2 = vec1.release(); // give up ownership of pointers in 'vec1' and pass the ownership to 'vec2', rather cheap + vec2.release(); // give up ownership; the objects will be deallocated if not assigned to another container + vec1 = vec2; // compile time error: 'operator=()' not defined + ptr_vector vec3( vec1 ); // compile time error: copy-constructor not defined + + +.. _`Example 4`: + +4. Making a non-copyable type Clonable +++++++++++++++++++++++++++++++++++++++ + +:: + + // a class that has no normal copy semantics + class X : boost::noncopyable { public: X* clone() const; ... }; + + // this will be found by the library by argument dependent lookup + X* allocate_clone( const X& x ) + { return x.clone(); } + + // we can now use the interface that requires clonability + ptr_vector vec1, vec2; + ... + vec2 = vec1.clone(); // 'clone()' requires cloning + vec2.insert( vec2.end(), vec1.begin(), vec1.end() ); // inserting always means inserting clones + + +.. _`Example 5`: + +5. Objects are cloned before insertion, inserted pointers are owned by the container +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +:: + + class X { ... }; // assume 'X' is Clonable + X x; // and 'X' can be stack-allocated + ptr_list list; + list.push_back( x ); // clone 'x' and then insert the resulting pointer + list.push_back( allocate_clone( x ); // do it manually + list.push_back( new X ); // always give the pointer directly to the container to avoid leaks + list.push_back( &x ); // don't do this!!! + + +.. _`Example 6`: + +6. Transferring ownership of a single element ++++++++++++++++++++++++++++++++++++++++++++++ + +:: + + ptr_deque deq; + typedef ptr_deque::auto_type auto_type; + + // ... fill the container somehow + + auto_type ptr = deq.release_back(); // remove back element from container and give up ownership + auto_type ptr2 = deq.release( deq.begin() + 2 ); // use an iterator to determine the element to release + ptr = deq.release_front(); // supported for 'ptr_list' and 'ptr_deque' + + + +.. _`Example 7`: + +7. Transferring ownership of pointers between different pointer containers +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +:: + + + ptr_list list; ptr_vector vec; + ... + // + // note: no cloning happens in these examples + // + list.transfer( list.begin(), vec.begin(), vec ); // make the first element of 'vec' the first element of 'list' + vec.transfer( vec.end(), list.begin(), list.end(), list ); // put all the lists element into the vector + + +.. _`Example 8`: + + + +8. Selected test files +++++++++++++++++++++++ + +:incomplete_type_test.cpp_: Shows how to implement the Composite pattern. +:simple_test.cpp_: Shows how the usage of pointer container compares with a + container of pointer pointers +:view_example.cpp_: Shows how to use a pointer container as a view into other container +:tree_test.cpp_: Shows how to make a tree-structure +:array_test.cpp_: Shows how to make an n-ary tree + +.. _incomplete_type_test.cpp : ../test/incomplete_type_test.cpp +.. _simple_test.cpp : ../test/simple_test.cpp +.. _view_example.cpp : ../test/view_example.cpp +.. _tree_test.cpp : ../test/tree_test.cpp +.. _array_test.cpp : ../test/ptr_array.cpp + + +9. A large example +++++++++++++++++++ + +This examples shows many of the most common +features at work. + +.. raw:: html + :file: tut1.html + +10. Changing the Clone Allocator +++++++++++++++++++++++++++++++++ + +This example shows how we can change +the Clone Allocator to use the pointer containers +as view into other containers: + +.. raw:: html + :file: tut2.html + +**Navigate:** + +- `home `_ +- `reference `_ + diff --git a/doc/faq.html b/doc/faq.html new file mode 100644 index 0000000..f06acb1 --- /dev/null +++ b/doc/faq.html @@ -0,0 +1,104 @@ + + + + + + +FAQ + + + +
+

FAQ

+ + + +
+

Which mutating algorithms are safe to use with pointers?

+

Any mutating algorithm that moves elements around by swapping them. An +important example is std::sort(); examples of unsafe algorithms are +std::unique() and std::remove().

+ +
+
+

Why does ptr_map<T>::insert()/replace() take two arguments (the key and the pointer) instead of one std::pair? And why is the key passed by non-const reference?

+

This is the only way the function can be implemented in an exception-safe +manner; since the copy-constructor of the key might throw, and since +function arguments are not guaranteed to be evaluated from left to right, +we need to ensure that evaluating the first argument does not throw. +Passing the key as a reference achieves just that.

+
+
+

When instantiating a pointer container with a type T, is T then allowed to be incomplete at that point?

+

No. This is a distinct property of shared_ptr which implies some overhead.

+

However, one can leave T incomplete in the header file:

+
+// foo.hpp
+class Foo { ... };
+new_clone( const Foo& ) { ... }
+delete_clone( const Foo* )     { ... }
+
+// x.hpp
+class Foo; // Foo is incomplete here
+class X { ptr_deque<Foo> container; ... }
+
+// x.cpp
+#include <x.hpp>
+#include <foo.hpp> // now Foo is not incomplete anymore
+...
+
+
+
+

Why do iterator-range inserts give the strong exception-safety guarantee?

+

Is this not very inefficient? It is because it is actually affordable to +do so; the overhead is one heap-allocation which is relatively small +compared to cloning N objects.

+
+
+

What is the polymorphic class problem?

+

The problem refers to the relatively troublesome way C++ supports Object +Oriented programming in connection with containers of pointers to +polymorphic objects. In a language without garbage collection, you end up +using either a container of pointer pointers or a container that takes +ownership of the pointers. The hard part is to find a safe, fast and +elegant solution.

+
+
+

Are the pointer containers faster and do they have a better memory footprint than a container of pointer pointers?

+

The short answer is yes: they are faster and they do use less memory; in +fact, they are the only way to obtain the zero-overhead hallmark of C++. +Smart pointers usually have one word or more of memory overhead per +pointer because a reference count must be maintained. And since the +reference count must be maintained, there is also a runtime-overhead. If +your objects are big, then the memory overhead is often negligible, but if +you have many small objects, it is not. Further reading can be found in +these references: [11] and [12].

+
+
+

When the stored pointers cannot be 0, how do I allow this "empty" behavior anyway?

+

Storing a null-pointer among a list of pointers does not fit well into the Object Oriented paradigm. +The most elegant design is to use the Null-Object Pattern where one basically makes a concrete +class with dummy implementations of the virtual functions. See [13] for details.

+
+
+ + diff --git a/doc/faq.rst b/doc/faq.rst new file mode 100755 index 0000000..bce57f2 --- /dev/null +++ b/doc/faq.rst @@ -0,0 +1,94 @@ +=== +FAQ +=== + +.. contents:: :local: + +Since a pointer container is not Copy Constructible and Assignable, I cannot put them into standard containers; what do I do? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +Since they are `Clonable `_, you simply put them in a pointer container. + +Calling ``assign()`` is very costly and I do not really need to store cloned objects; I merely need to overwrite the existing ones; what do I do? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +Call ``std::copy( first, last, c.begin() );``. + +Which mutating algorithms are safe to use with pointers? +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +Any mutating algorithm that moves elements around by swapping them. An +important example is ``std::sort()``; examples of unsafe algorithms are +``std::unique()`` and ``std::remove()``. + +.. That is why these algorithms are + provided as member functions. + +Why does ``ptr_map::insert()/replace()`` take two arguments (the key and the pointer) instead of one ``std::pair``? And why is the key passed by non-const reference? +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +This is the only way the function can be implemented in an exception-safe +manner; since the copy-constructor of the key might throw, and since +function arguments are not guaranteed to be evaluated from left to right, +we need to ensure that evaluating the first argument does not throw. +Passing the key as a reference achieves just that. + +When instantiating a pointer container with a type ``T``, is ``T`` then allowed to be incomplete at that point? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +No. This is a distinct property of ``shared_ptr`` which implies some overhead. + +However, one can leave ``T`` incomplete in the header file:: + + // foo.hpp + class Foo { ... }; + new_clone( const Foo& ) { ... } + delete_clone( const Foo* ) { ... } + + // x.hpp + class Foo; // Foo is incomplete here + class X { ptr_deque container; ... } + + // x.cpp + #include + #include // now Foo is not incomplete anymore + ... + + + +Why do iterator-range inserts give the strong exception-safety guarantee? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +Is this not very inefficient? It is because it is actually affordable to +do so; the overhead is one heap-allocation which is relatively small +compared to cloning N objects. + +What is the _`polymorphic class problem`? ++++++++++++++++++++++++++++++++++++++++++ + +The problem refers to the relatively troublesome way C++ supports Object +Oriented programming in connection with containers of pointers to +polymorphic objects. In a language without garbage collection, you end up +using either a container of pointer pointers or a container that takes +ownership of the pointers. The hard part is to find a safe, fast and +elegant solution. + +Are the pointer containers faster and do they have a better memory footprint than a container of pointer pointers? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +The short answer is yes: they are faster and they do use less memory; in +fact, they are the only way to obtain the zero-overhead hallmark of C++. +Smart pointers usually have one word or more of memory overhead per +pointer because a reference count must be maintained. And since the +reference count must be maintained, there is also a runtime-overhead. If +your objects are big, then the memory overhead is often negligible, but if +you have many small objects, it is not. Further reading can be found in +these references: `[11] `_ and `[12] `_. + +When the stored pointers cannot be ``0``, how do I allow this "empty" behavior anyway? +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +Storing a null-pointer among a list of pointers does not fit well into the Object Oriented paradigm. +The most elegant design is to use the Null-Object Pattern where one basically makes a concrete +class with dummy implementations of the virtual functions. See `[13] `_ for details. + diff --git a/doc/guidelines.html b/doc/guidelines.html new file mode 100644 index 0000000..fdb28fc --- /dev/null +++ b/doc/guidelines.html @@ -0,0 +1,36 @@ + + + + + + +Usage Guidelines + + + +
+

Usage Guidelines

+

The recommended usage pattern of the container classes are the same as the +for normal standard containers.

+

ptr_vector, ptr_list and ptr_deque offer the programmer different +complexity tradeoffs and should be used accordingly. ptr_vector is the +type of sequence that should be used by default. ptr_list should be used +when there are frequent insertions and deletions from the middle of the +sequence and if the container is fairly large (eg. more than 100 +elements). ptr_deque is the data structure of choice when most insertions +and deletions take place at the beginning or at the end of the sequence. +The special container ptr_array may be used when the size of the container is invariant +and known at compile time.

+

An associative container supports unique keys if it may contain at most +one element for each key. Otherwise, it supports equivalent keys. +ptr_set and ptr_map support unique keys. +ptr_multiset and ptr_multimap +support equivalent keys.

+

Navigate:

+ +
+ + diff --git a/doc/guidelines.rst b/doc/guidelines.rst new file mode 100755 index 0000000..97a391c --- /dev/null +++ b/doc/guidelines.rst @@ -0,0 +1,29 @@ +================ +Usage Guidelines +================ + +The recommended usage pattern of the container classes are the same as the +for normal standard containers. + +``ptr_vector``, ``ptr_list`` and ``ptr_deque`` offer the programmer different +complexity tradeoffs and should be used accordingly. ``ptr_vector`` is the +type of sequence that should be used by default. ``ptr_list`` should be used +when there are frequent insertions and deletions from the middle of the +sequence and if the container is fairly large (eg. more than 100 +elements). ``ptr_deque`` is the data structure of choice when most insertions +and deletions take place at the beginning or at the end of the sequence. +The special container ``ptr_array`` may be used when the size of the container is invariant +and known at compile time. + +An associative container supports unique keys if it may contain at most +one element for each key. Otherwise, it supports equivalent keys. +``ptr_set`` and ``ptr_map`` support unique keys. +``ptr_multiset`` and ``ptr_multimap`` +support equivalent keys. + +**Navigate:** + +- `home `_ +- `reference `_ + + diff --git a/doc/headers.html b/doc/headers.html new file mode 100644 index 0000000..4662b5b --- /dev/null +++ b/doc/headers.html @@ -0,0 +1,83 @@ + + + + + + +Library headers + + + +
+

Library headers

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
HeaderIncludes
<boost/ptr_container/clone_allocator.hpp>classes heap_clone_allocator and view_clone_allocator +and functions allocate_clone() and delete_clone()
<boost/ptr_container/ptr_deque.hpp>class ptr_deque (and std::deque)
<boost/ptr_container/ptr_list.hpp>class ptr_list (and std::list)
<boost/ptr_container/ptr_vector.hpp>class ptr_vector (and std::vector)
<boost/ptr_container/ptr_array.hpp>class ptr_array (and boost::array)
<boost/ptr_container/ptr_set>
+
classes ptr_set and ptr_multiset
+
(and std::set and std::multiset)
+
+
<boost/ptr_container/ptr_map>
+
classes ptr_map and ptr_multimap
+
(and std::map and std::multimap)
+
+
<boost/ptr_container/ptr_sequence_adapter.hpp>class ptr_sequence_adapter
<boost/ptr_container/ptr_set_adapter.hpp>classes ptr_set_adapter and ptr_multiset_adapter
<boost/ptr_container/ptr_map_adapter.hpp>classes ptr_map_adapter and ptr_multimap_adapter
<boost/ptr_container/exception.hpp>
+
classes bad_ptr_container_operation, bad_index
+
and bad_pointer
+
+
<boost/ptr_container/indirect_fun.hpp>class indirect_fun
<boost/ptr_container/nullable.hpp>class nullable
+

Navigate:

+ +
+ + diff --git a/doc/headers.rst b/doc/headers.rst new file mode 100755 index 0000000..fa6eb8f --- /dev/null +++ b/doc/headers.rst @@ -0,0 +1,47 @@ +=============== +Library headers +=============== + +======================================================= ============================================================= + **Header** **Includes** + +```` classes heap_clone_allocator_ and view_clone_allocator_ + and functions ``allocate_clone()`` and ``delete_clone()`` + +```` class `ptr_deque `_ (and ``std::deque``) + +```` class `ptr_list `_ (and ``std::list``) + +```` class `ptr_vector `_ (and ``std::vector``) + +```` class `ptr_array `_ (and ``boost::array``) + +```` classes `ptr_set `_ and `ptr_multiset `_ + (and ``std::set`` and ``std::multiset``) + +```` classes `ptr_map `_ and `ptr_multimap `_ + (and ``std::map`` and ``std::multimap``) + +```` class `ptr_sequence_adapter `_ + +```` classes `ptr_set_adapter `_ and `ptr_multiset_adapter `_ + +```` classes `ptr_map_adapter `_ and `ptr_multimap_adapter `_ + +```` classes ``bad_ptr_container_operation``, ``bad_index`` + and ``bad_pointer`` +```` class ``indirect_fun`` + +```` class ``nullable`` +======================================================= ============================================================= + +.. _`heap_clone_allocator`: reference.html#the-clone-allocator-concept +.. _`view_clone_allocator`: reference.html#the-clone-allocator-concept + +**Navigate:** + +- `home `_ +- `reference `_ + + + diff --git a/doc/indirect_fun.html b/doc/indirect_fun.html new file mode 100644 index 0000000..0909bd9 --- /dev/null +++ b/doc/indirect_fun.html @@ -0,0 +1,126 @@ + + + + + + +Indirected functions + + + +
+

Indirected functions

+

It is quite common that we have two pointers and what to compare the +pointed to objects. Also, we have usually already defined how +to compare the objects. So to avoid some tedious boiler-plate code +this library defines predicates that apply an indirection before comparing.

+

When the container uses void* internally, we can use the +class void_ptr_indirect_fun; otherwise we use the class +indirect_fun.

+

Example:

+
+std::string* bar = new std::string("bar");
+std::string* foo = new std::string("foo");
+BOOST_ASSERT( indirect_fun< std::less<std::string> >()( bar, foo ) == true );
+BOOST_ASSERT( make_indirect_fun( std::less<std::string>() )( foo, bar ) == false );   
+
+void*       vptr1  = ptr1;
+void*       vptr2  = ptr2;
+void_ptr_indirect_fun< std::less<std::string>, std::string> cast_fun;
+BOOST_CHECK( cast_fun( vptr1, vptr2 ) == true );
+
+

See also:

+ +

Navigate

+ +

Remarks:

+

The class indirect_fun will work with smart pointers such as boost::shared_ptr<T> +because of the type traits pointee<T>::type from the header <boost/pointee.hpp>.

+

Synopsis:

+

Since the definition of the predicates is somewhat trivial, only the +first operation is expanded inline.

+
+namespace boost
+{      
+
+    template< class Fun >
+    struct indirect_fun
+    {
+        indirect_fun() : fun(Fun())
+        { }
+        
+        indirect_fun( Fun f ) : fun(f)
+        { }
+    
+        template< class T >
+        typename result_of< Fun( typename pointee<T>::type ) >::type 
+        operator()( const T& r ) const
+        { 
+            return fun( *r );
+        }
+    
+        template< class T, class U >
+        typename result_of< Fun( typename pointee<T>::type, 
+                                               typename pointee<U>::type ) >::type 
+        operator()( const T& r, const U& r2 ) const
+        { 
+            return fun( *r, *r2 );
+        }
+    
+    private:
+        Fun fun;
+    };
+
+    template< class Fun >
+    inline indirect_fun<Fun> make_indirect_fun( Fun f )
+    {
+        return indirect_fun<Fun>( f );
+    }        
+
+
+
+    template< class Fun, class Arg1, class Arg2 = Arg1 >
+    struct void_ptr_indirect_fun
+    {
+        void_ptr_indirect_fun() : fun(Fun())
+        { }
+
+        void_ptr_indirect_fun( Fun f ) : fun(f)
+        { }
+
+        typename result_of< Fun( Arg1 ) >::type 
+        operator()( const void* r ) const
+        { 
+            return fun( * static_cast<const Arg1*>( r ) );
+        }
+
+        typename result_of< Fun( Arg1, Arg2 ) >::type 
+        operator()( const void* l, const void* r ) const
+        { 
+            return fun( * static_cast<const Arg1*>( l ), * static_cast<const Arg2*>( r ) );
+        }
+        
+    private:
+        Fun fun;   
+    };
+
+    template< class Fun, class Arg >
+    inline void_ptr_indirect_fun<Fun,Arg> 
+    make_void_ptr_indirect_fun( Fun f )
+    {
+        return void_ptr_indirect_fun<Fun,Arg>( f );
+    }
+         
+} // namespace 'boost'  
+
+
+ + diff --git a/doc/indirect_fun.rst b/doc/indirect_fun.rst new file mode 100755 index 0000000..18d1fb5 --- /dev/null +++ b/doc/indirect_fun.rst @@ -0,0 +1,123 @@ +Indirected functions +-------------------- + +It is quite common that we have two pointers and what to compare the +pointed to objects. Also, we have usually already defined how +to compare the objects. So to avoid some tedious boiler-plate code +this library defines predicates that apply an indirection before comparing. + +When the container uses ``void*`` internally, we can use the +class ``void_ptr_indirect_fun``; otherwise we use the class +``indirect_fun``. + +**Example:** :: + + std::string* bar = new std::string("bar"); + std::string* foo = new std::string("foo"); + BOOST_ASSERT( indirect_fun< std::less >()( bar, foo ) == true ); + BOOST_ASSERT( make_indirect_fun( std::less() )( foo, bar ) == false ); + + void* vptr1 = ptr1; + void* vptr2 = ptr2; + void_ptr_indirect_fun< std::less, std::string> cast_fun; + BOOST_CHECK( cast_fun( vptr1, vptr2 ) == true ); + +**See also:** + +- `result_of `_ +- `pointee `_ +- `ptr_set `_ +- `ptr_multiset `_ + +**Navigate** + +- `home `_ +- `reference `_ + +**Remarks:** + +The class ``indirect_fun`` will work with smart pointers such as `boost::shared_ptr `_ +because of the type traits ``pointee::type`` from the header ````. + +**Synopsis:** + +Since the definition of the predicates is somewhat trivial, only the +first operation is expanded inline. + +:: + + namespace boost + { + + template< class Fun > + struct indirect_fun + { + indirect_fun() : fun(Fun()) + { } + + indirect_fun( Fun f ) : fun(f) + { } + + template< class T > + typename result_of< Fun( typename pointee::type ) >::type + operator()( const T& r ) const + { + return fun( *r ); + } + + template< class T, class U > + typename result_of< Fun( typename pointee::type, + typename pointee::type ) >::type + operator()( const T& r, const U& r2 ) const + { + return fun( *r, *r2 ); + } + + private: + Fun fun; + }; + + template< class Fun > + inline indirect_fun make_indirect_fun( Fun f ) + { + return indirect_fun( f ); + } + + + + template< class Fun, class Arg1, class Arg2 = Arg1 > + struct void_ptr_indirect_fun + { + void_ptr_indirect_fun() : fun(Fun()) + { } + + void_ptr_indirect_fun( Fun f ) : fun(f) + { } + + typename result_of< Fun( Arg1 ) >::type + operator()( const void* r ) const + { + return fun( * static_cast( r ) ); + } + + typename result_of< Fun( Arg1, Arg2 ) >::type + operator()( const void* l, const void* r ) const + { + return fun( * static_cast( l ), * static_cast( r ) ); + } + + private: + Fun fun; + }; + + template< class Fun, class Arg > + inline void_ptr_indirect_fun + make_void_ptr_indirect_fun( Fun f ) + { + return void_ptr_indirect_fun( f ); + } + + } // namespace 'boost' + + + diff --git a/doc/intro.xml b/doc/intro.xml new file mode 100644 index 0000000..d967772 --- /dev/null +++ b/doc/intro.xml @@ -0,0 +1,79 @@ + + +
+ Introduction + + + This library provides standard-like containers that are suitable + for storing pointers to both polymorphic and non-polymorphic objects. + For each of the standard containers there is a pointer container + equivalent that takes ownership of the stored pointers in an exception + safe manner. In this respect it is intended to solve + the so-called polymorphic class problem. + + + The main advantages are + + Exception-safe and fool proof pointer storage and manipulation.. + Exception-guarantees are generally much better than with standard containers (at least the strong guarantee + Notational convinience compared to the use of containers of smart pointers. + Iterators are automatically indirected so the comparison operations can be kept + on object basis instead of making/adding pointer based variants. + No memory-overhead as containers of smart_pointers can have. + Faster than using containers of smart pointers. + Provides an elegant solution to vector< vector > performance + problems; simply use ptr_vector< vector > + + + Below is given some example that show how the usage compares to a container of smart pointers: + + using namespace boost; + using namespace std; + + class Poly + { + public: + virtual ~Poly() {} + void foo() { doFoo(); } + private: + virtual void doFoo() + { + int i; + ++i; + } + }; + + // + // one doesn't need to introduce new names or live with long ones + // + typedef shared_ptr PolyPtr; + + // + // one doesn't need to write this anymore + // + struct PolyPtrOps + { + void operator()( const PolyPtr & a ) + { a->foo(); } + }; + + int main() + { + enum { size = 2000000 }; + vector svec + ptr_vector pvec; + + for( int i = 0; i < size; ++i ) + { + svec.push_back( PolyPtr( new Poly ) ); + pvec.push_back( new Poly ); // no extra syntax + } + + for_each( svec.begin(), svec.end(), PolyPtrOps() ); + + for_each( pvec.begin(), pvec.end(), mem_fun_ref( &Poly::foo ) ); + } + + +
diff --git a/doc/ptr_array.html b/doc/ptr_array.html new file mode 100644 index 0000000..87fada0 --- /dev/null +++ b/doc/ptr_array.html @@ -0,0 +1,254 @@ + + + + + + + + + + +
+
+

Class ptr_array

+

A ptr_array<T,size> is a pointer container that uses an underlying boost::array<void*,size> +to store the pointers. The class is useful when there is no requirement +of dynamic expansion and when absolute no overhead is tolerable.

+

See also:

+ +

Navigate:

+ +

Synopsis:

+
+namespace boost
+{      
+
+    template
+    < 
+        class T, 
+        size_t N, 
+        CloneAllocator = heap_clone_allocator
+    >
+    class ptr_array : public implementation-defined
+    {
+    public: // construct/copy/destroy
+        ptr_array();
+        ptr_array( std::auto_ptr<ptr_array>& r );
+
+    public: // iterators
+
+    public: // capacity
+
+    public: // element access
+        T&        front();
+        const T&  front() const;
+        T&        back();
+        const T&  back() const;
+        
+        template< size_t idx >
+        T&        at();
+        template< size_t idx >
+        const T&  at() const;
+        T&        at( size_t );
+        const T&  at( size_t );
+
+        T&        operator[]( size_t );
+        const T&  operator[]( size_t ) const;
+
+    public: // modifiers
+        void  swap( ptr_array& r );
+
+        template< size_t idx >
+        auto_type replace( T* r );
+        auto_type replace( size_t idx, T* r );
+
+    public: // pointer container requirements
+        std::auto_ptr<ptr_array>  clone() const;    
+        std::auto_ptr<ptr_array>  release();
+        template< size_t idx >
+        bool                      is_null() const;
+        bool                      is_null( size_t idx ) const;
+     
+    }; //  class 'ptr_sequence_adapter'
+
+} // namespace 'boost'  
+
+
+
+

Semantics

+
+

Semantics: construct/copy/destroy

+
    +
  • ptr_array();

    +
    +
      +
    • Effects: construct array where each element is null
    • +
    +
    +
  • +
  • ptr_array( std::auto_ptr<ptr_array>& r );

    +
    +
      +
    • Effects: take ownership of the supplied pointers
    • +
    +
    +
  • +
+
+
+

Semantics: element access

+
    +
  • T&       front();

    +
  • +
  • const T& front() const;

    +
    +
      +
    • Requirements: not empty();
    • +
    • Effects: return *begin();
    • +
    • Throws: bad_ptr_container_operation if empty() == true
    • +
    +
    +
  • +
  • T&       back();

    +
  • +
  • const T& back() const;

    +
    +
      +
    • Requirements: not empty();
    • +
    • Effects: return *--end();
    • +
    • Throws: bad_ptr_container_operation if empty() == true
    • +
    +
    +
  • +
  • template< size_t idx > T&       at( size_type n );

    +
  • +
  • template< size_t idx > const T& at( size_type n ) const;

    +
    +
      +
    • Requirements: idx < size() (compile-time enforced)
    • +
    • Effects: Returns a reference to the n'th element
    • +
    • Throws: nothing
    • +
    +
    +
  • +
  • T&       at( size_type n );

    +
  • +
  • const T& at( size_type n ) const;

    +
    +
      +
    • Requirements: n < size()
    • +
    • Effects: Returns a reference to the n'th element
    • +
    • Throws: bad_index if n >=size()
    • +
    +
    +
  • +
  • T&       operator[]( size_type n );

    +
  • +
  • const T& operator[]( size_type n ) const;

    +
    +
      +
    • Requirements: n < size()
    • +
    • Effects: Returns a reference to the n'th element
    • +
    • Throws: Nothing
    • +
    +
    +
  • +
+
+
+

Semantics: modifiers

+
    +
  • void swap( ptr_array& r );

    +
    +
      +
    • Effects: swaps the two arrays
    • +
    • Complexity: Linear
    • +
    • Throws: nothing
    • +
    +
    +
  • +
  • template< size_t idx > auto_type replace( T* r );

    +
    +
      +
    • Requirements:

      +
      +
        +
      • idx < size() (compile-time enforced)
      • +
      • r != 0
      • +
      +
      +
    • +
    • Effects: returns the object indexed by idx and replaces it with r.

      +
    • +
    • Throws: bad_pointer if x == 0.

      +
    • +
    • Exception safety: Strong guarantee

      +
    • +
    +
    +
  • +
  • auto_type replace( size_t idx, T* r );

    +
    +
      +
    • Requirements: `` x != 0 and idx < size()``
    • +
    • Effects: returns the object indexed by idx and replaces it with x.
    • +
    • Throws: bad_index if idx >= size() and bad_pointer if x == 0.
    • +
    • Exception safety: Strong guarantee
    • +
    +
    +
  • +
+
+
+

Semantics: pointer container requirements

+
    +
  • std::auto_ptr<ptr_array>  clone() const;

    +
    +
      +
    • Effects: Returns a deep copy of the container
    • +
    • Throws: std::bad_alloc if there is not enough memory to make a clone of the container
    • +
    • Complexity: Linear
    • +
    +
    +
  • +
  • std::auto_ptr<ptr_array>  release();

    +
    +
      +
    • Effects: Releases ownership of the container. This is a useful way of returning a container from a function.
    • +
    • Postconditions: empty() == true and all pointers are null
    • +
    • Throws: std::bad_alloc if the return value cannot be allocated
    • +
    • Exception safety: Strong guarantee
    • +
    +
    +
  • +
  • template< size_t idx > bool is_null() const;

    +
    +
      +
    • Requirements: idx < size() (compile-time enforced)
    • +
    • Effects: returns whether the pointer at index idx is null
    • +
    • Exception safety: Nothrow guarantee
    • +
    +
    +
  • +
  • bool is_null( size_type idx ) const;

    +
    +
      +
    • Requirements: idx < size()
    • +
    • Effects: returns whether the pointer at index idx is null
    • +
    • Exception safety: Nothrow guarantee
    • +
    +
    +
  • +
+
+
+
+ + diff --git a/doc/ptr_array.rst b/doc/ptr_array.rst new file mode 100755 index 0000000..9759d61 --- /dev/null +++ b/doc/ptr_array.rst @@ -0,0 +1,237 @@ + +Class ``ptr_array`` +------------------- + +A ``ptr_array`` is a pointer container that uses an underlying ``boost::array`` +to store the pointers. The class is useful when there is no requirement +of dynamic expansion and when absolute no overhead is tolerable. + +**See also:** + +- reversible_ptr_container_ +- ptr_sequence_adapter_ +- ptr_vector_ + +.. _reversible_ptr_container: reversible_ptr_container.html +.. _ptr_sequence_adapter: ptr_sequence_adapter.html +.. _ptr_vector: ptr_vector.html + +**Navigate:** + +- `home `_ +- `reference `_ + + + +**Synopsis:** + +.. parsed-literal:: + + namespace boost + { + + template + < + class T, + size_t N, + CloneAllocator = heap_clone_allocator + > + class ptr_array : public *implementation-defined* + { + public: // `construct/copy/destroy`_ + ptr_array(); + ptr_array( std::auto_ptr& r ); + + public: // `iterators`_ + + public: // `capacity`_ + + public: // `element access`_ + T& front(); + const T& front() const; + T& back(); + const T& back() const; + + template< size_t idx > + T& at(); + template< size_t idx > + const T& at() const; + T& at( size_t ); + const T& at( size_t ); + + T& operator[]( size_t ); + const T& operator[]( size_t ) const; + + public: // `modifiers`_ + void swap( ptr_array& r ); + + template< size_t idx > + auto_type replace( T* r ); + auto_type replace( size_t idx, T* r ); + + public: // `pointer container requirements`_ + std::auto_ptr clone() const; + std::auto_ptr release(); + template< size_t idx > + bool is_null() const; + bool is_null( size_t idx ) const; + + }; // class 'ptr_sequence_adapter' + + } // namespace 'boost' + +.. _iterators: reversible_ptr_container.html#iterators + +.. _capacity: reversible_ptr_container.html#capacity + +.. _`inherited element access`: reversible_ptr_container.html#element-access + +Semantics +--------- + +.. _`construct/copy/destroy`: + +Semantics: construct/copy/destroy +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- ``ptr_array();`` + + - Effects: construct array where each element is null + +- ``ptr_array( std::auto_ptr& r );`` + + - Effects: take ownership of the supplied pointers + +.. _`element access`: + +Semantics: element access +^^^^^^^^^^^^^^^^^^^^^^^^^ + + +- ``T& front();`` +- ``const T& front() const;`` + + - Requirements: ``not empty();`` + + - Effects: ``return *begin();`` + + - Throws: ``bad_ptr_container_operation`` if ``empty() == true`` + + +- ``T& back();`` +- ``const T& back() const;`` + + - Requirements: ``not empty();`` + + - Effects: ``return *--end();`` + + - Throws: ``bad_ptr_container_operation`` if ``empty() == true`` + +- ``template< size_t idx > T& at( size_type n );`` +- ``template< size_t idx > const T& at( size_type n ) const;`` + + - Requirements: ``idx < size()`` (compile-time enforced) + + - Effects: Returns a reference to the ``n``'th element + + - Throws: nothing + +- ``T& at( size_type n );`` +- ``const T& at( size_type n ) const;`` + + - Requirements: ``n < size()`` + + - Effects: Returns a reference to the ``n``'th element + + - Throws: ``bad_index`` if ``n >=size()`` + + +- ``T& operator[]( size_type n );`` +- ``const T& operator[]( size_type n ) const;`` + + - Requirements: ``n < size()`` + + - Effects: Returns a reference to the ``n``'th element + + - Throws: Nothing + + +.. _`modifiers`: + +Semantics: modifiers +^^^^^^^^^^^^^^^^^^^^ + +- ``void swap( ptr_array& r );`` + + - Effects: swaps the two arrays + + - Complexity: Linear + + - Throws: nothing + +- ``template< size_t idx > auto_type replace( T* r );`` + + - Requirements: + + - ``idx < size()`` (compile-time enforced) + - ``r != 0`` + + - Effects: returns the object indexed by ``idx`` and replaces it with ``r``. + + - Throws: ``bad_pointer`` if ``x == 0``. + + - Exception safety: Strong guarantee + +- ``auto_type replace( size_t idx, T* r );`` + + - Requirements: `` x != 0 and idx < size()`` + + - Effects: returns the object indexed by ``idx`` and replaces it with ``x``. + + - Throws: ``bad_index`` if ``idx >= size()`` and ``bad_pointer`` if ``x == 0``. + + - Exception safety: Strong guarantee + + +.. _`pointer container requirements`: + +Semantics: pointer container requirements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- ``std::auto_ptr clone() const;`` + + - Effects: Returns a deep copy of the container + + - Throws: ``std::bad_alloc`` if there is not enough memory to make a clone of the container + + - Complexity: Linear + + +- ``std::auto_ptr release();`` + + - Effects: Releases ownership of the container. This is a useful way of returning a container from a function. + + - Postconditions: ``empty() == true`` and all pointers are null + + - Throws: ``std::bad_alloc`` if the return value cannot be allocated + + - Exception safety: Strong guarantee + + +- ``template< size_t idx > bool is_null() const;`` + + - Requirements: ``idx < size()`` (compile-time enforced) + + - Effects: returns whether the pointer at index ``idx`` is null + + - Exception safety: Nothrow guarantee + +- ``bool is_null( size_type idx ) const;`` + + - Requirements: ``idx < size()`` + + - Effects: returns whether the pointer at index ``idx`` is null + + - Exception safety: Nothrow guarantee + + diff --git a/doc/ptr_container.html b/doc/ptr_container.html new file mode 100644 index 0000000..50b2c36 --- /dev/null +++ b/doc/ptr_container.html @@ -0,0 +1,224 @@ + + + + + + +Boost Pointer Container Library + + + + + + +
+

Boost Pointer Container Library

+ +++ + + + + + + + + + + + +
Author:Thorsten Ottosen
Contact:nesotto@cs.auc.dk
organizations:Department of Computer Science, Aalborg University, and Dezide Aps
Date:24th of September
Copyright:Thorsten Ottosen 2004. Use, modification and distribution is subject to the Boost Software License, Version 1.0 (see LICENSE_1_0.txt).
+
+

Overview

+

Boost.Pointer Container provides containers for holding heap-allocated +objects in an exception-safe manner and with minimal overhead. +The aim of the library is in particular to make OO programming +easier in C++ by establishing a standard set of classes, methods +and designs for dealing with OO specific problems

+ +
+
+

Motivation

+

Whenever a programmer wants to have a container of pointers to +heap-allocated objects, there is usually only one exception-safe way: +to make a container of pointer pointers like boost::shared_ptr. +This approach is suboptimal if

+
    +
  1. the stored objects are not shared, but owned exclusively, or
  2. +
  3. the overhead implied by pointer pointers is inappropriate
  4. +
+

This library therefore provides standard-like containers that are for storing +heap-allocated or cloned objects (or in case of a map, the mapped object must be +a heap-allocated or cloned object). For each of the standard +containers there is a pointer container equivalent that takes ownership of +the objects in an exception safe manner. In this respect the library is intended +to solve the so-called +polymorphic class problem.

+

The advantages of pointer containers are

+
    +
  1. Exception-safe pointer storage and manipulation.
  2. +
  3. Notational convenience compared to the use of containers of pointers.
  4. +
  5. Can be used for types that are neither Assignable nor Copy Constructible.
  6. +
  7. No memory-overhead as containers of pointer pointers can have (see [11] and [12]).
  8. +
  9. Usually faster than using containers of pointer pointers (see [11] and [12]).
  10. +
  11. The interface is slightly changed towards the domain of pointers +instead of relying on the normal value-based interface. For example, +now it is possible for pop_back() to return the removed element.
  12. +
+

The disadvantages are

+
    +
  1. Less flexible than containers of pointer pointers
  2. +
+
+
+

Portability

+

The review version has been tested with

+
    +
  • vc7.1
  • +
  • gcc 3.3.3
  • +
  • como 4.3.3 (+dinkumware lib)
  • +
+

and it requires the current boost-cvs to work.

+

There is known problems with

+
    +
  • libcomo: some really irritating concept-checking prohibits vector<T*> if T is abstract.
  • +
+
+
+

Acknowledgements

+

The following people have been helpful:

+
    +
  • Bjørn D. Rasmussen for showing me his crappy code that motivated me to start this library
  • +
  • Pavel Vozenilek for asking me to make the adapters
  • +
  • David Abrahams for the indirect_fun design
  • +
  • Pavol Droba for being review manager
  • +
  • Ross Boylan for trying out a prototype for real
  • +
  • Felipe Magno de Almeida for giving fedback based on using the +library in production code even before the library was part of boost
  • +
  • Jonathan Turkanis for supplying his move_ptr framework +which is used internally
  • +
+
+
+

References

+ + + + + +
[1]Matt Austern: "The Standard Librarian: Containers of Pointers" , C/C++ Users Journal Experts Forum.
+ + + + + +
[2]Bjarne Stroustrup, "The C++ Programming Language", Appendix E: "Standard-Library Exception Safety"
+ + + + + +
[3]Herb Sutter, "Exceptional C++".
+ + + + + +
[4]Herb Sutter, "More Exceptional C++".
+ + + + + +
[5]Kevlin Henney: "From Mechanism to Method: The Safe Stacking of Cats" , C++ Experts Forum, February 2002.
+ + + + + +
[6]Some of the few earlier attempts of pointer containers I have seen are the rather interesting NTL and the +pointainer. +As of this writing both libraries are not exceptions-safe and can leak.
+ + + + + +
[7]INTERNATIONAL STANDARD, Programming languages --- C++, ISO/IEC 14882, 1998. See section 23 in particular.
+ + + + + +
[8]C++ Standard Library Closed Issues List (Revision 27), +Item 218, Algorithms do not use binary predicate objects for default comparisons.
+ + + + + +
[9]C++ Standard Library Active Issues List (Revision 27), +Item 226, User supplied specializations or overloads of namespace std function templates.
+ + + + + +
[10]Harald Nowak, "A remove_if for vector", C/C++ Users Journal, July 2001.
+ + + + + +
[11](1, 2) Boost smart pointer timings
+ + + + + +
[12](1, 2) NTL: Array vs std::vector and boost::shared_ptr
+ + + + + +
[13]Kevlin Henney, Null Object, 2002.
+
+
+ + diff --git a/doc/ptr_container.rst b/doc/ptr_container.rst new file mode 100755 index 0000000..7067a90 --- /dev/null +++ b/doc/ptr_container.rst @@ -0,0 +1,189 @@ + +++++++++++++++++++++++++++++++++++ + |Boost| Pointer Container Library +++++++++++++++++++++++++++++++++++ + +.. |Boost| image:: cboost.gif + + + +:Authors: Thorsten Ottosen +:Contact: nesotto@cs.auc.dk +:organizations: `Department of Computer Science`_, Aalborg University, and `Dezide Aps`_ +:date: 24th of September +:copyright: Thorsten Ottosen 2004. Use, modification and distribution is subject to the Boost Software License, Version 1.0 (see LICENSE_1_0.txt__). + +__ http://www.boost.org/LICENSE_1_0.txt + +.. _`Department of Computer Science`: http://www.cs.auc.dk +.. _`Dezide Aps`: http://www.dezide.com + +======== +Overview +======== + +Boost.Pointer Container provides containers for holding heap-allocated +objects in an exception-safe manner and with minimal overhead. +The aim of the library is in particular to make OO programming +easier in C++ by establishing a standard set of classes, methods +and designs for dealing with OO specific problems + +* Motivation_ +* Tutorial_ +* Reference_ + + - `Conventions `_ + - `The Clonable Concept `_ + - `The Clone Allocator Concept `_ + - `Pointer container adapters `_ + - `Sequence container classes `_ + + - `ptr_vector `_ + - `ptr_deque `_ + - `ptr_list `_ + - `ptr_array `_ + - `Associative container classes `_ + + - `ptr_set `_ + - `ptr_multiset `_ + - `ptr_map `_ + - `ptr_multimap `_ + - `Indirected functions `_ + - `Class nullable `_ + - `Exception classes `_ +* `Usage guidelines`_ +* Examples_ +* `Library headers`_ +* Portability_ +* FAQ_ +* Acknowledgements_ +* References_ + + +.. _Tutorial: tutorial.html + + +.. _Reference: reference.html + +.. _`Usage guidelines`: guidelines.html + +.. _Examples: examples.html + +.. _`Library headers`: headers.html + +.. _FAQ: faq.html + + +========== +Motivation +========== + +Whenever a programmer wants to have a container of pointers to +heap-allocated objects, there is usually only one exception-safe way: +to make a container of pointer pointers like ``boost::shared_ptr``. +This approach is suboptimal if + +1. the stored objects are not shared, but owned exclusively, or +2. the overhead implied by pointer pointers is inappropriate + +This library therefore provides standard-like containers that are for storing +heap-allocated or `cloned `_ objects (or in case of a map, the mapped object must be +a heap-allocated or cloned object). For each of the standard +containers there is a pointer container equivalent that takes ownership of +the objects in an exception safe manner. In this respect the library is intended +to solve the so-called +`polymorphic class problem `_. + + +The advantages of pointer containers are + +1. Exception-safe pointer storage and manipulation. +2. Notational convenience compared to the use of containers of pointers. +3. Can be used for types that are neither Assignable nor Copy Constructible. +4. No memory-overhead as containers of pointer pointers can have (see [11]_ and [12]_). +5. Usually faster than using containers of pointer pointers (see [11]_ and [12]_). +6. The interface is slightly changed towards the domain of pointers + instead of relying on the normal value-based interface. For example, + now it is possible for ``pop_back()`` to return the removed element. + +The disadvantages are + +1. Less flexible than containers of pointer pointers + +=========== +Portability +=========== + +The review version has been tested with + +- vc7.1 +- gcc 3.3.3 +- como 4.3.3 (+dinkumware lib) + +and it requires the current boost-cvs to work. + +There is known problems with + +- libcomo: some really irritating concept-checking prohibits ``vector`` if ``T`` is abstract. + +================ +Acknowledgements +================ + +The following people have been helpful: + +- Bjørn D. Rasmussen for showing me his crappy code that motivated me to start this library +- Pavel Vozenilek for asking me to make the adapters +- David Abrahams for the ``indirect_fun`` design +- Pavol Droba for being review manager +- Ross Boylan for trying out a prototype for real +- Felipe Magno de Almeida for giving fedback based on using the + library in production code even before the library was part of boost +- Jonathan Turkanis for supplying his ``move_ptr`` framework + which is used internally + +========== +References +========== + +.. [1] Matt Austern: `"The Standard Librarian: Containers of Pointers"`__ , C/C++ Users Journal Experts Forum. + +__ http://www.cuj.com/documents/s=7990/cujcexp1910austern/ + +.. [2] Bjarne Stroustrup, "The C++ Programming Language", `Appendix E: "Standard-Library Exception Safety"`__ + +__ http://www.research.att.com/~bs/3rd_safe.pdf + +.. [3] Herb Sutter, "Exceptional C++". +.. [4] Herb Sutter, "More Exceptional C++". +.. [5] Kevlin Henney: `"From Mechanism to Method: The Safe Stacking of Cats"`__ , C++ Experts Forum, February 2002. + +__ http://www.cuj.com/documents/s=7986/cujcexp2002henney/henney.htm + +.. [6] Some of the few earlier attempts of pointer containers I have seen are the rather interesting NTL_ and the + pointainer_. + As of this writing both libraries are not exceptions-safe and can leak. + +.. [7] INTERNATIONAL STANDARD, Programming languages --- C++, ISO/IEC 14882, 1998. See section 23 in particular. +.. [8] C++ Standard Library Closed Issues List (Revision 27), + Item 218, `Algorithms do not use binary predicate objects for default comparisons`__. + +__ http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-closed.html#218 + +.. [9] C++ Standard Library Active Issues List (Revision 27), + Item 226, `User supplied specializations or overloads of namespace std function templates`__. + +__ http://gcc.gnu.org/onlinedocs/libstdc++/ext/lwg-active.html#226 + +.. [10] Harald Nowak, "A remove_if for vector", C/C++ Users Journal, July 2001. +.. [11] Boost smart pointer timings__ + +__ http://www.boost.org/libs/ptr_ptr/smarttests.htm + +.. [12] NTL_: Array vs std::vector and boost::shared_ptr +.. [13] Kevlin Henney, `Null Object`__, 2002. + +__ http://www.two-sdg.demon.co.uk/curbralan/papers/europlop/NullObject.pdf + +.. _NTL: http://www.ntllib.org/asp.html +.. _pointainer: http://ootips.org/yonat/4dev/pointainer.h diff --git a/doc/ptr_container.xml b/doc/ptr_container.xml new file mode 100644 index 0000000..89e4259 --- /dev/null +++ b/doc/ptr_container.xml @@ -0,0 +1,43 @@ + + + + + + + Thorsten + Ottosen + + + + 2003 + Thorsten Ottosen + + + + Permission to copy, use, sell and distribute this software + is granted provided this copyright notice appears in all copies. + Permission to modify the code and to distribute modified code is + granted provided this copyright notice appears in all copies, and + a notice that the code was modified is included with the copyright + notice. + + This software is provided "as is" without express or + implied warranty, and with no claim as to its suitability for any + purpose. + + + + This library provides standard-like containers that are suitable + for storing pointers to both polymorphic and non-polymorphic objects. + + + + + Boost Pointer Container Library + + + + diff --git a/doc/ptr_deque.html b/doc/ptr_deque.html new file mode 100644 index 0000000..371deae --- /dev/null +++ b/doc/ptr_deque.html @@ -0,0 +1,153 @@ + + + + + + + + + + +
+
+

Class ptr_deque

+

A ptr_deque<T> is a pointer container that uses an underlying std:deque<void*> +to store the pointers.

+

See also:

+ +

Navigate:

+ +

Synopsis:

+
+namespace boost
+{      
+
+    template
+    < 
+        class T, 
+        class CloneAllocator = heap_clone_allocator
+        class Allocator      = std::allocator<void*>
+    >
+    class ptr_deque : public ptr_sequence_adapter
+                             <
+                                T,
+                                std::deque<void*,Allocator>,
+                                CloneAllocator
+                             >
+    {
+
+    public: // element access
+        T&        operator[]( size_type n );
+        const T&  operator[]( size_type n ) const;
+        T&        at( size_type n );
+        const T&  at( size_type n ) const;
+
+    public: // modifiers
+        void      push_front( T* x );
+        auto_type pop_front();
+
+    public: // pointer container requirements
+       auto_type replace( size_type idx, T* x );    
+       bool      is_null( size_type idx ) const;   
+
+    };
+
+} // namespace 'boost'  
+
+
+
+

Semantics

+
+

Semantics: modifiers

+
    +
  • void push_front( T* x );

    +
    +
      +
    • Requirements: x != 0
    • +
    • Effects: Inserts the pointer into container and takes ownership of it
    • +
    • Throws: bad_pointer if x == 0
    • +
    • Exception safety: Strong guarantee
    • +
    +
    +
  • +
+ +
    +
  • auto_type pop_front():

    +
    +
      +
    • Requirements:not empty()
    • +
    • Effects: Removes the first element in the container
    • +
    • Postconditions: size() is one less
    • +
    • Throws: bad_ptr_container_operation if empty() == true
    • +
    • Exception safety: Strong guarantee
    • +
    +
    +
  • +
+
+
+

Semantics: element access

+
    +
  • T& operator[]( size_type n );

    +
  • +
  • const T& operator[]( size_type n ) const;

    +
    +
      +
    • Requirements: n < size()
    • +
    • Effects: Returns a reference to the n'th element
    • +
    • Throws: Nothing
    • +
    +
    +
  • +
  • T& at( size_type n );

    +
  • +
  • const T& at( size_type n ) const;

    +
    +
      +
    • Requirements: n < size()
    • +
    • Effects: Returns a reference to the n'th element
    • +
    • Throws: bad_index if n >=size()
    • +
    +
    +
  • +
+
+
+

Semantics: pointer container requirements

+
    +
  • auto_type replace( size_type idx, T* x );

    +
    +
      +
    • Requirements: `` x != 0 and idx < size()``
    • +
    • Effects: returns the object indexed by idx and replaces it with x.
    • +
    • Throws: bad_index if idx >= size() and bad_pointer if x == 0.
    • +
    • Exception safety: Strong guarantee
    • +
    +
    +
  • +
  • bool is_null( size_type idx ) const;

    +
    +
      +
    • Requirements: idx < size()
    • +
    • Effects: returns whether the pointer at index idx is null
    • +
    • Exception safety: Nothrow guarantee
    • +
    +
    +
  • +
+
+
+
+ + diff --git a/doc/ptr_deque.rst b/doc/ptr_deque.rst new file mode 100755 index 0000000..407620b --- /dev/null +++ b/doc/ptr_deque.rst @@ -0,0 +1,150 @@ +Class ``ptr_deque`` +-------------------- + +A ``ptr_deque`` is a pointer container that uses an underlying ``std:deque`` +to store the pointers. + +**See also:** + +- reversible_ptr_container_ +- ptr_sequence_adapter_ + +.. _reversible_ptr_container: reversible_ptr_container.html +.. _ptr_map: ptr_map.html + +**Navigate:** + +- `home `_ +- `reference `_ + + +**Synopsis:** + +.. parsed-literal:: + + namespace boost + { + + template + < + class T, + class CloneAllocator = heap_clone_allocator + class Allocator = std::allocator + > + class ptr_deque : public ptr_sequence_adapter + < + T, + std::deque, + CloneAllocator + > + { + + public: // `element access`_ + T& operator[]( size_type n ); + const T& operator[]( size_type n ) const; + T& at( size_type n ); + const T& at( size_type n ) const; + + public: // modifiers_ + void push_front( T* x ); + auto_type pop_front(); + + public: // `pointer container requirements`_ + auto_type replace( size_type idx, T* x ); + bool is_null( size_type idx ) const; + + }; + + } // namespace 'boost' + + +.. _`reversible_ptr_container`: reversible_ptr_container.html + +.. _`ptr_sequence_adapter`: ptr_sequence_adapter.html + +Semantics +--------- + +.. _modifiers: + +Semantics: modifiers +^^^^^^^^^^^^^^^^^^^^ + +- ``void push_front( T* x );`` + + - Requirements: ``x != 0`` + + - Effects: Inserts the pointer into container and takes ownership of it + + - Throws: ``bad_pointer`` if ``x == 0`` + + - Exception safety: Strong guarantee + + +.. + - ``void push_front( const T& x );`` + + - Effects: push_front( allocate_clone( x ) ); + + - Exception safety: Strong guarantee + +- ``auto_type pop_front():`` + + - Requirements:``not empty()`` + + - Effects: Removes the first element in the container + + - Postconditions: ``size()`` is one less + + - Throws: ``bad_ptr_container_operation`` if ``empty() == true`` + + - Exception safety: Strong guarantee + + +.. _`element access`: + +Semantics: element access +^^^^^^^^^^^^^^^^^^^^^^^^^ + +- ``T& operator[]( size_type n );`` +- ``const T& operator[]( size_type n ) const;`` + + - Requirements: ``n < size()`` + + - Effects: Returns a reference to the ``n``'th element + + - Throws: Nothing + +- ``T& at( size_type n );`` +- ``const T& at( size_type n ) const;`` + + - Requirements: ``n < size()`` + + - Effects: Returns a reference to the ``n``'th element + + - Throws: ``bad_index`` if ``n >=size()`` + + +.. _`pointer container requirements`: + +Semantics: pointer container requirements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- ``auto_type replace( size_type idx, T* x );`` + + - Requirements: `` x != 0 and idx < size()`` + + - Effects: returns the object indexed by ``idx`` and replaces it with ``x``. + + - Throws: ``bad_index`` if ``idx >= size()`` and ``bad_pointer`` if ``x == 0``. + + - Exception safety: Strong guarantee + +- ``bool is_null( size_type idx ) const;`` + + - Requirements: ``idx < size()`` + + - Effects: returns whether the pointer at index ``idx`` is null + + - Exception safety: Nothrow guarantee + diff --git a/doc/ptr_list.html b/doc/ptr_list.html new file mode 100644 index 0000000..5ad39ce --- /dev/null +++ b/doc/ptr_list.html @@ -0,0 +1,146 @@ + + + + + + + + + + +
+
+

Class ptr_vector

+

A ptr_list<T> is a pointer container that uses an underlying std:list<void*> +to store the pointers.

+

See also:

+ +

Navigate:

+ +

Synopsis:

+
+namespace boost
+{      
+
+    template
+    < 
+        class T, 
+        class CloneAllocator = heap_clone_allocator,
+        class Allocator      = std::allocator<void*>
+    >
+    class ptr_list : public ptr_sequence_adapter
+                            <
+                                T,
+                                std::list<void*,Allocator>,
+                                CloneAllocator
+                            >
+    {
+    
+    public: // modifiers
+        void                push_front( T* x );
+        auto_type           pop_front();
+     
+    public: // list operations
+        void  merge( ptr_list& x ); 
+        template< typename Compare > 
+        void  merge( ptr_list& x, Compare comp );
+        
+        void  reverse();
+
+    }; // class 'ptr_list'
+
+} // namespace 'boost'  
+
+
+
+

Semantics

+
+

Semantics: modifiers

+
    +
  • void push_front( T* x );

    +
    +
      +
    • Requirements: x != 0
    • +
    • Effects: Inserts the pointer into container and takes ownership of it
    • +
    • Throws: bad_pointer if x == 0
    • +
    • Exception safety: Strong guarantee
    • +
    +
    +
  • +
+ +
    +
  • auto_type pop_front():

    +
    +
      +
    • Requirements:not empty()
    • +
    • Effects: Removes the first element in the container
    • +
    • Postconditions: size() is one less
    • +
    • Throws: bad_ptr_container_operation if empty() == true
    • +
    • Exception safety: Strong guarantee
    • +
    +
    +
  • +
+
+
+

Semantics: list operations

+ +
    +
  • void merge( ptr_list& x );

    +
    +
      +
    • Not ready yet
    • +
    +
    +
  • +
  • template< typename Compare > +void merge( ptr_list& x, Compare comp );

    +
    +
      +
    • Not ready yet
    • +
    +
    +
  • +
  • void reverse();

    +
    +
      +
    • Effects: reverses the underlying sequence
    • +
    • Throws: nothing
    • +
    +
    +
  • +
+
+
+
+ + diff --git a/doc/ptr_list.rst b/doc/ptr_list.rst new file mode 100755 index 0000000..98978cb --- /dev/null +++ b/doc/ptr_list.rst @@ -0,0 +1,135 @@ +Class ``ptr_vector`` +-------------------- + +A ``ptr_list`` is a pointer container that uses an underlying ``std:list`` +to store the pointers. + +**See also:** + +- reversible_ptr_container_ +- ptr_sequence_adapter_ + +.. _reversible_ptr_container: reversible_ptr_container.html +.. _ptr_array: ptr_array.html +.. _`ptr_sequence_adapter`: ptr_sequence_adapter.html + +**Navigate:** + +- `home `_ +- `reference `_ + + +**Synopsis:** + +.. parsed-literal:: + + namespace boost + { + + template + < + class T, + class CloneAllocator = heap_clone_allocator, + class Allocator = std::allocator + > + class ptr_list : public ptr_sequence_adapter + < + T, + std::list, + CloneAllocator + > + { + + public: // modifiers_ + void push_front( T* x ); + auto_type pop_front(); + + public: // `list operations`_ + void merge( ptr_list& x ); + template< typename Compare > + void merge( ptr_list& x, Compare comp ); + + void reverse(); + + }; // class 'ptr_list' + + } // namespace 'boost' + + +Semantics +--------- + +.. _modifiers: + +Semantics: modifiers +^^^^^^^^^^^^^^^^^^^^ + +- ``void push_front( T* x );`` + + - Requirements: ``x != 0`` + + - Effects: Inserts the pointer into container and takes ownership of it + + - Throws: ``bad_pointer`` if ``x == 0`` + + - Exception safety: Strong guarantee + +.. + - ``void push_front( const T& x );`` + + - Effects: push_front( allocate_clone( x ) ); + + - Exception safety: Strong guarantee + +- ``auto_type pop_front():`` + + - Requirements:``not empty()`` + + - Effects: Removes the first element in the container + + - Postconditions: ``size()`` is one less + + - Throws: ``bad_ptr_container_operation`` if ``empty() == true`` + + - Exception safety: Strong guarantee + +.. _`list operations`: + +Semantics: list operations +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. + - ``void splice( iterator before, ptr_list& x );`` + + - Requirements:``&x != this`` + + - Effects: inserts the all of ``x``'s elements before ``before`` + + - Postconditions: ``x.empty()`` + + - Throws: nothing + + - Remark: prefer this to ``transfer( before, x );`` + + - ``void splice( iterator before, ptr_list& x, iterator i );`` + + - Not ready yet + + - ``void splice( iterator before, ptr_list& x, iterator first, iterator last );`` + + - Not ready yet + +- ``void merge( ptr_list& x );`` + + - Not ready yet + +- ``template< typename Compare > + void merge( ptr_list& x, Compare comp );`` + + - Not ready yet + +- ``void reverse();`` + + - Effects: reverses the underlying sequence + + - Throws: nothing diff --git a/doc/ptr_map.html b/doc/ptr_map.html new file mode 100644 index 0000000..cd9702a --- /dev/null +++ b/doc/ptr_map.html @@ -0,0 +1,56 @@ + + + + + + +Class ptr_map + + + +
+

Class ptr_map

+

A ptr_map<Key,T> is a pointer container that uses an underlying std::map<Key,void*> +to store the pointers.

+

See also:

+ + +

Navigate:

+ +

Synopsis:

+
+namespace boost
+{
+
+    template
+    < 
+        class Key, 
+        class T, 
+        class Compare        = std::less<Key>, 
+        class CloneAllocator = heap_clone_allocator,
+        class Allocator      = std::allocator< std::pair<const Key,void*> >
+    >
+    class ptr_map : public ptr_map_adapter
+                           <
+                               T,
+                               std::map<Key,void*,Compare,Allocator>,
+                               CloneAllocator
+                           >
+    {
+        // see references
+        
+    }; //  class 'ptr_map'
+
+} // namespace 'boost'  
+
+
+ + diff --git a/doc/ptr_map.rst b/doc/ptr_map.rst new file mode 100755 index 0000000..e64bb56 --- /dev/null +++ b/doc/ptr_map.rst @@ -0,0 +1,54 @@ +Class ``ptr_map`` +----------------- + +A ``ptr_map`` is a pointer container that uses an underlying ``std::map`` +to store the pointers. + +**See also:** + +- reversible_ptr_container_ +- associative_ptr_container_ +- ptr_map_adapter_ +- `new map iterators `_ + +.. _reversible_ptr_container: reversible_ptr_container.html +.. _associative_ptr_container: associative_ptr_container.html +.. _ptr_map_adapter: ptr_map_adapter.html +.. class `indirect_fun `_ + + +**Navigate:** + +- `home `_ +- `reference `_ + + +**Synopsis:** + +.. parsed-literal:: + + + namespace boost + { + + template + < + class Key, + class T, + class Compare = std::less, + class CloneAllocator = heap_clone_allocator, + class Allocator = std::allocator< std::pair > + > + class ptr_map : public ptr_map_adapter + < + T, + std::map, + CloneAllocator + > + { + // see references + + }; // class 'ptr_map' + + } // namespace 'boost' + diff --git a/doc/ptr_map_adapter.html b/doc/ptr_map_adapter.html new file mode 100644 index 0000000..335d141 --- /dev/null +++ b/doc/ptr_map_adapter.html @@ -0,0 +1,158 @@ + + + + + + + + + + +
+
+

Class ptr_map_adapter

+

This class is used to build custom pointer containers with +an underlying map-like container. The interface of the class is an extension +of the interface from associative_ptr_container.

+

See also:

+ +

Navigate:

+ +

Synopsis:

+
+namespace boost
+{
+    template
+    < 
+        class T,
+        class VoidPtrMap, 
+        class CloneAllocator = heap_clone_allocator 
+    >
+    class ptr_map_adapter 
+    {
+        
+    public: // modifiers         
+        std::pair<iterator,bool>  insert( key_type& k, value_type x );                         
+
+    public; // lookup
+        T&       operator[]( const key_type& key );
+        T&       at( const key_type& key );
+        const T& at( const key_type& key ) const;
+        
+    public: // pointer container requirements
+        bool      transfer( iterator object, ptr_map_adapter& from );
+        size_type transfer( iterator first, iterator last, ptr_map_adapter& from );
+        template< class Range >
+        size_type transfer( const Range& r, ptr_map_adapter& from );
+        size_type transfer( ptr_map_adapter& from );
+            
+    }; //  class 'ptr_map_adapter'
+
+} // namespace 'boost'  
+
+
+
+

Semantics

+
+

Semantics: modifiers

+
    +
  • std::pair<iterator,bool> insert( key_type& k, value_type x );

    +
    +
      +
    • Requirements: x != 0
    • +
    • Effects: Takes ownership of x and insert it iff there is no equivalent of it already. The bool part of the return value indicates insertion and the iterator points to the element with key x.
    • +
    • Throws: bad_pointer if x == 0
    • +
    • Exception safety: Strong guarantee
    • +
    +
    +
  • +
+ +
+
+

Semantics: lookup

+
    +
  • T& operator[]( const key_type& key );

    +
    +
      +
    • Effects: returns the object with key key if it exists; otherwise a new object is allocated and inserted and its reference returned.
    • +
    • Exception-safety: Strong guarantee
    • +
    +
    +
  • +
  • T&       at( const key_type& key );

    +
  • +
  • const T& at( const key_type& jey ) const;

    +
    +
      +
    • Requirement: the key exists
    • +
    • Throws: bad_ptr_container_operation if the key does not exist
    • +
    +
    +
  • +
+
+
+

Semantics: pointer container requirements

+
    +
  • bool transfer( iterator object, ptr_map_adapter& from );

    +
    +
      +
    • Requirements: not from.empty()
    • +
    • Effects: Inserts the object defined by object into the container and remove it from from +iff no equivalent object exists.
    • +
    • Returns: whether the object was transfered
    • +
    • Exception safety: Strong guarantee
    • +
    +
    +
  • +
  • size_type transfer( iterator first, iterator last, ptr__set_adapter& from );

    +
    +
      +
    • Requirements: not from.empty()
    • +
    • Effects: Inserts the objects defined by the range [first,last) into the container and remove it from from. +An object is only transferred if no equivalent object exists.
    • +
    • Returns: the number of transfered objects
    • +
    • Exception safety: Basic guarantee
    • +
    +
    +
  • +
  • template< class Range > void transfer( const Range& r, ptr_map_adapter& from );

    +
    +
      +
    • Effects: return transfer( boost::begin(r), boost::end(r), from );
    • +
    +
    +
  • +
  • size_type transfer( ptr_set_adapter& from );

    +
    +
      +
    • Effects: return transfer( from.begin(), from.end(), from );.
    • +
    +
    +
  • +
+
+
+
+

Docutils System Messages

+
+

System Message: ERROR/3 (ptr_map_adapter.rst)

+Anonymous hyperlink mismatch: 0 references but 1 targets. +See "backrefs" attribute for IDs.
+
+
+ + diff --git a/doc/ptr_map_adapter.rst b/doc/ptr_map_adapter.rst new file mode 100755 index 0000000..2f3359a --- /dev/null +++ b/doc/ptr_map_adapter.rst @@ -0,0 +1,139 @@ +Class ``ptr_map_adapter`` +------------------------- + +This class is used to build custom pointer containers with +an underlying map-like container. The interface of the class is an extension +of the interface from ``associative_ptr_container``. + +**See also:** + +- reversible_ptr_container_ +- associative_ptr_container_ +- ptr_map_ +- `new map iterators `_ + +.. _reversible_ptr_container: reversible_ptr_container.html +.. _associative_ptr_container: associative_ptr_container.html +.. _ptr_map: ptr_map.html + +**Navigate:** + +- `home `_ +- `reference `_ + +**Synopsis:** + +.. parsed-literal:: + + + namespace boost + { + template + < + class T, + class VoidPtrMap, + class CloneAllocator = heap_clone_allocator + > + class ptr_map_adapter + { + + public: // `modifiers`_ + std::pair insert( key_type& k, value_type x ); + + public; // `lookup`_ + T& operator[]( const key_type& key ); + T& at( const key_type& key ); + const T& at( const key_type& key ) const; + + public: // `pointer container requirements`_ + bool transfer( iterator object, ptr_map_adapter& from ); + size_type transfer( iterator first, iterator last, ptr_map_adapter& from ); + template< class Range > + size_type transfer( const Range& r, ptr_map_adapter& from ); + size_type transfer( ptr_map_adapter& from ); + + }; // class 'ptr_map_adapter' + + } // namespace 'boost' + + +Semantics +--------- + +.. _`modifiers`: + +Semantics: modifiers +^^^^^^^^^^^^^^^^^^^^ + +- ``std::pair insert( key_type& k, value_type x );`` + + - Requirements: ``x != 0`` + + - Effects: Takes ownership of ``x`` and insert it iff there is no equivalent of it already. The bool part of the return value indicates insertion and the iterator points to the element with key ``x``. + + - Throws: bad_pointer if ``x == 0`` + + - Exception safety: Strong guarantee + + +.. + - ``std::pair insert( key_type& k, const_reference x );`` + + - Effects: ``return insert( allocate_clone( x ) );`` + + - Exception safety: Strong guarantee + + +.. _`lookup`: + +Semantics: lookup +^^^^^^^^^^^^^^^^^ + +- ``T& operator[]( const key_type& key );`` + + - Effects: returns the object with key ``key`` if it exists; otherwise a new object is allocated and inserted and its reference returned. + - Exception-safety: Strong guarantee + +- ``T& at( const key_type& key );`` +- ``const T& at( const key_type& jey ) const;`` + + - Requirement: the key exists + - Throws: ``bad_ptr_container_operation`` if the key does not exist + +.. _`pointer container requirements`: + +Semantics: pointer container requirements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- ``bool transfer( iterator object, ptr_map_adapter& from );`` + + - Requirements: ``not from.empty()`` + + - Effects: Inserts the object defined by ``object`` into the container and remove it from ``from`` + iff no equivalent object exists. + + - Returns: whether the object was transfered + + - Exception safety: Strong guarantee + +- ``size_type transfer( iterator first, iterator last, ptr__set_adapter& from );`` + + - Requirements: ``not from.empty()`` + + - Effects: Inserts the objects defined by the range ``[first,last)`` into the container and remove it from ``from``. + An object is only transferred if no equivalent object exists. + + - Returns: the number of transfered objects + + - Exception safety: Basic guarantee + +- ``template< class Range > void transfer( const Range& r, ptr_map_adapter& from );`` + + - Effects: ``return transfer( boost::begin(r), boost::end(r), from );`` + +- ``size_type transfer( ptr_set_adapter& from );`` + + - Effects: ``return transfer( from.begin(), from.end(), from );``. + + + diff --git a/doc/ptr_multimap.html b/doc/ptr_multimap.html new file mode 100644 index 0000000..2c2d87e --- /dev/null +++ b/doc/ptr_multimap.html @@ -0,0 +1,54 @@ + + + + + + +Class ptr_multimap + + + +
+

Class ptr_multimap

+

A ptr_multimap<Key,T> is a pointer container that uses an underlying std::multimap<Key,void*> +to store the pointers.

+

See also:

+ +

Navigate:

+ +

Synopsis:

+
+namespace boost
+{
+    template
+    < 
+        class Key, 
+        class T, 
+        class Compare        = std::less<Key>,
+        class CloneAllocator = heap_clone_allocator,
+        class Allocator      = std::allocator< std::pair<const Key,void*> >
+    >
+    class ptr_multimap : public ptr_multimap_adapter
+                                <
+                                    T,
+                                    std::multimap<Key,void*,Compare,Allocator>,
+                                    CloneAllocator
+                                >
+    {
+        // see references
+        
+    }; //  class 'ptr_multimap'
+
+} // namespace 'boost'  
+
+
+ + diff --git a/doc/ptr_multimap.rst b/doc/ptr_multimap.rst new file mode 100755 index 0000000..0c801ec --- /dev/null +++ b/doc/ptr_multimap.rst @@ -0,0 +1,52 @@ +Class ``ptr_multimap`` +---------------------- + +A ``ptr_multimap`` is a pointer container that uses an underlying ``std::multimap`` +to store the pointers. + +**See also:** + +- reversible_ptr_container_ +- associative_ptr_container_ +- ptr_multimap_adapter_ +- `new map iterators `_ + +**Navigate:** + +- `home `_ +- `reference `_ + +.. _reversible_ptr_container: reversible_ptr_container.html +.. _associative_ptr_container: associative_ptr_container.html +.. _ptr_multimap_adapter: ptr_multimap_adapter.html + + + +**Synopsis:** + +.. parsed-literal:: + + + namespace boost + { + template + < + class Key, + class T, + class Compare = std::less, + class CloneAllocator = heap_clone_allocator, + class Allocator = std::allocator< std::pair > + > + class ptr_multimap : public ptr_multimap_adapter + < + T, + std::multimap, + CloneAllocator + > + { + // see references + + }; // class 'ptr_multimap' + + } // namespace 'boost' + diff --git a/doc/ptr_multimap_adapter.html b/doc/ptr_multimap_adapter.html new file mode 100644 index 0000000..abdba0e --- /dev/null +++ b/doc/ptr_multimap_adapter.html @@ -0,0 +1,134 @@ + + + + + + + + + + +
+
+

Class ptr_multimap_adapter

+

This class is used to build custom pointer containers with +an underlying multimap-like container. The interface of the class is an extension +of the interface from associative_ptr_container.

+

See also:

+ +

Navigate:

+ +

Synopsis:

+
+namespace boost
+{
+    template
+    < 
+        T,
+        class VoidPtrMultiMap,
+        class CloneAllocator = heap_clone_allocator 
+    >
+    class ptr_multimap_adapter 
+    {
+        
+    public: // modifiers         
+        iterator  insert( key_type& k, T* x );                         
+
+    public: // pointer container requirements
+        void      transfer( iterator object, ptr_multimap_adapter& from );
+        size_type transfer( iterator first, iterator last, ptr_multimap_adapter& from );
+        template< class Range >
+        size_type transfer( const Range& r, ptr_multimap_adapter& from );
+        void      transfer( ptr_multimap_adapter& from );
+
+    }; //  class 'ptr_multimap_adapter'
+
+} // namespace 'boost'  
+
+
+
+

Semantics

+
+

Semantics: modifiers

+
    +
  • iterator insert( key_type& k, T* x );

    +
    +
      +
    • Requirements: x != 0
    • +
    • Effects: Takes ownership of x and returns an iterator pointing to it.
    • +
    • Throws: bad_pointer if x == 0
    • +
    • Exception safety: Strong guarantee
    • +
    +
    +
  • +
+ + +
+
+

Semantics: pointer container requirements

+
    +
  • void transfer( iterator object, ptr_multimap_adapter& from );

    +
    +
      +
    • Requirements: not from.empty()
    • +
    • Effects: Inserts the object defined by object into the container and remove it from from.
    • +
    • Postconditions: size() is one more, from.size() is one less.
    • +
    • Exception safety: Strong guarantee
    • +
    +
    +
  • +
  • void transfer( iterator first, iterator last, ptr_multimap_adapter& from );

    +
    +
      +
    • Requirements: not from.empty()
    • +
    • Effects: Inserts the objects defined by the range [first,last) into the container and remove it from from.
    • +
    • Postconditions: Let N == std::distance(first,last); then size() is N more, from.size() is N less.
    • +
    • Exception safety: Basic guarantee
    • +
    +
    +
  • +
  • template< class Range > void transfer( const Range& r, ptr_multimap_adapter& from );

    +
    +
      +
    • Effects: transfer( boost::begin(r), boost::end(r), from );
    • +
    +
    +
  • +
  • void transfer( ptr_multimap_adapter& from );

    +
    +
      +
    • Effects: transfer( from.begin(), from.end(), from );.
    • +
    • Postconditions: from.empty();
    • +
    • Exception safety: Basic guarantee
    • +
    +
    +
  • +
+
+
+
+ + diff --git a/doc/ptr_multimap_adapter.rst b/doc/ptr_multimap_adapter.rst new file mode 100755 index 0000000..fe88942 --- /dev/null +++ b/doc/ptr_multimap_adapter.rst @@ -0,0 +1,135 @@ +Class ``ptr_multimap_adapter`` +------------------------------ + +This class is used to build custom pointer containers with +an underlying multimap-like container. The interface of the class is an extension +of the interface from ``associative_ptr_container``. + +**See also:** + +- reversible_ptr_container_ +- associative_ptr_container_ +- ptr_multimap_ +- `new map iterators`__ + +.. _reversible_ptr_container: reversible_ptr_container.html +.. _associative_ptr_container: associative_ptr_container.html +.. _ptr_multimap: ptr_multimap.html +__ ptr_container.html#map-iterator-operations + +**Navigate:** + +- `home `_ +- `reference `_ + +**Synopsis:** + +.. parsed-literal:: + + + namespace boost + { + template + < + T, + class VoidPtrMultiMap, + class CloneAllocator = heap_clone_allocator + > + class ptr_multimap_adapter + { + + public: // `modifiers`_ + iterator insert( key_type& k, T* x ); + + public: // `pointer container requirements`_ + void transfer( iterator object, ptr_multimap_adapter& from ); + size_type transfer( iterator first, iterator last, ptr_multimap_adapter& from ); + template< class Range > + size_type transfer( const Range& r, ptr_multimap_adapter& from ); + void transfer( ptr_multimap_adapter& from ); + + }; // class 'ptr_multimap_adapter' + + } // namespace 'boost' + + +Semantics +--------- + +.. _`modifiers`: + +Semantics: modifiers +^^^^^^^^^^^^^^^^^^^^ + +- ``iterator insert( key_type& k, T* x );`` + + - Requirements: ``x != 0`` + + - Effects: Takes ownership of ``x`` and returns an iterator pointing to it. + + - Throws: bad_pointer if ``x == 0`` + + - Exception safety: Strong guarantee + + +.. + - ``iterator insert( key_type& k, const_reference x );`` + + - Effects: ``return insert( allocate_clone( x ) );`` + + - Exception safety: Strong guarantee + + +.. _`lookup`: + +.. + Semantics: lookup + ^^^^^^^^^^^^^^^^^ + + - ``reference operator[]( const Key& key );`` + - ``const_reference operator[]( const Key& key ) const;`` + + - Requirements: the key exists + + - Effects: returns the object with key ``key`` + + - Throws: ``bad_ptr_container_operation`` if the key does not exist + +.. _`pointer container requirements`: + +Semantics: pointer container requirements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- ``void transfer( iterator object, ptr_multimap_adapter& from );`` + + - Requirements: ``not from.empty()`` + + - Effects: Inserts the object defined by ``object`` into the container and remove it from ``from``. + + - Postconditions: ``size()`` is one more, ``from.size()`` is one less. + + - Exception safety: Strong guarantee + +- ``void transfer( iterator first, iterator last, ptr_multimap_adapter& from );`` + + - Requirements: ``not from.empty()`` + + - Effects: Inserts the objects defined by the range ``[first,last)`` into the container and remove it from ``from``. + + - Postconditions: Let ``N == std::distance(first,last);`` then ``size()`` is ``N`` more, ``from.size()`` is ``N`` less. + + - Exception safety: Basic guarantee + +- ``template< class Range > void transfer( const Range& r, ptr_multimap_adapter& from );`` + + - Effects: ``transfer( boost::begin(r), boost::end(r), from );`` + +- ``void transfer( ptr_multimap_adapter& from );`` + + - Effects: ``transfer( from.begin(), from.end(), from );``. + + - Postconditions: ``from.empty();`` + + - Exception safety: Basic guarantee + + diff --git a/doc/ptr_multiset.html b/doc/ptr_multiset.html new file mode 100644 index 0000000..3ed3616 --- /dev/null +++ b/doc/ptr_multiset.html @@ -0,0 +1,58 @@ + + + + + + +Class ptr_multiset + + + +
+

Class ptr_multiset

+

A ptr_multiset<T> is a pointer container that uses an underlying std::multiset<void*> +to store the pointers.

+

See also:

+ +

Navigate:

+ +

Synopsis:

+
+namespace boost
+{
+
+    template
+    < 
+        class Key, 
+        class Compare        = std::less<Key>,
+        class CloneAllocator = heap_clone_allocator,
+        class Allocator      = std::allocator<void*>
+    >
+    class ptr_multiset : public ptr_multiset_adapter
+                                <
+                                    Key,
+                                    std::multiset<void*,void_ptr_indirect_fun<Compare,Key>,Allocator>,
+                                    CloneAllocator
+                                >
+    {
+        // see references
+        
+    }; //  class 'ptr_multiset'
+
+} // namespace 'boost'  
+
+

Remarks:

+
    +
  • Using nullable<T> as Key is meaningless and not allowed
  • +
+
+ + diff --git a/doc/ptr_multiset.rst b/doc/ptr_multiset.rst new file mode 100755 index 0000000..66f5512 --- /dev/null +++ b/doc/ptr_multiset.rst @@ -0,0 +1,55 @@ +Class ``ptr_multiset`` +---------------------- + +A ``ptr_multiset`` is a pointer container that uses an underlying ``std::multiset`` +to store the pointers. + +**See also:** + +- reversible_ptr_container_ +- associative_ptr_container_ +- ptr_multiset_adapter_ +- `void_ptr_indirect_fun `_ + +.. _reversible_ptr_container: reversible_ptr_container.html +.. _associative_ptr_container: associative_ptr_container.html +.. _ptr_multiset_adapter: ptr_multiset_adapter.html +.. _`indirect predicates`: indirect_fun.html + +**Navigate:** + +- `home `_ +- `reference `_ + + +**Synopsis:** + +.. parsed-literal:: + + + namespace boost + { + + template + < + class Key, + class Compare = std::less, + class CloneAllocator = heap_clone_allocator, + class Allocator = std::allocator + > + class ptr_multiset : public ptr_multiset_adapter + < + Key, + std::multiset,Allocator>, + CloneAllocator + > + { + // see references + + }; // class 'ptr_multiset' + + } // namespace 'boost' + +**Remarks:** + +- Using ``nullable`` as ``Key`` is meaningless and not allowed diff --git a/doc/ptr_multiset_adapter.html b/doc/ptr_multiset_adapter.html new file mode 100644 index 0000000..7ea70a7 --- /dev/null +++ b/doc/ptr_multiset_adapter.html @@ -0,0 +1,122 @@ + + + + + + + + + + +
+
+

Class ptr_multiset_adapter

+

This class is used to build custom pointer containers with +an underlying multiset-like container. The interface of the class is an extension +of the interface from associative_ptr_container.

+

See also:

+ +

Navigate:

+ +

Synopsis:

+
+namespace boost
+{
+    template
+    < 
+        class Key,
+        class VoidPtrMultiSet,
+        class CloneAllocator = heap_clone_allocator
+    >
+    class ptr_multiset_adapter 
+    {
+        
+    public: // modifiers         
+        iterator  insert( Key* x );                         
+
+    public: // pointer container requirements
+        void      transfer( iterator object, ptr_multiset_adapter& from );
+        size_type transfer( iterator first, iterator last, ptr_multiset_adapter& from );
+        template< class Range >
+        size_type transfer( const Range& r, ptr_multiset_adapter& from );
+        void      transfer( ptr_multiset_adapter& from );
+
+    }; //  class 'ptr_multiset_adapter'
+
+} // namespace 'boost'  
+
+
+
+

Semantics

+
+

Semantics: modifiers

+
    +
  • iterator insert( key_type* x );

    +
    +
      +
    • Requirements: x != 0
    • +
    • Effects: Takes ownership of x. The returned iterator points to the element with key x.
    • +
    • Throws: bad_pointer if x == 0
    • +
    • Exception safety: Strong guarantee
    • +
    +
    +
  • +
+ +
+
+

Semantics: pointer container requirements

+
    +
  • void transfer( iterator object, ptr_multiset_adapter& from );

    +
    +
      +
    • Requirements: not from.empty()
    • +
    • Effects: Inserts the object defined by object into the container and remove it from from.
    • +
    • Postconditions: size() is one more, from.size() is one less.
    • +
    • Exception safety: Strong guarantee
    • +
    +
    +
  • +
  • void transfer( iterator first, iterator last, ptr_multiset_adapter& from );

    +
    +
      +
    • Requirements: not from.empty()
    • +
    • Effects: Inserts the objects defined by the range [first,last) into the container and remove it from from.
    • +
    • Postconditions: Let N == std::distance(first,last); then size() is N more, from.size() is N less.
    • +
    • Exception safety: Basic guarantee
    • +
    +
    +
  • +
  • template< class Range > void transfer( const Range& r, ptr_multiset_adapter& from );

    +
    +
      +
    • Effects: transfer( boost::begin(r), boost::end(r), from );
    • +
    +
    +
  • +
  • void transfer( ptr_multiset_adapter& from );

    +
    +
      +
    • Effects: transfer( from.begin(), from.end(), from );.
    • +
    • Postconditions: from.empty();
    • +
    • Exception safety: Basic guarantee
    • +
    +
    +
  • +
+
+
+
+ + diff --git a/doc/ptr_multiset_adapter.rst b/doc/ptr_multiset_adapter.rst new file mode 100755 index 0000000..9ed9a8d --- /dev/null +++ b/doc/ptr_multiset_adapter.rst @@ -0,0 +1,116 @@ +Class ``ptr_multiset_adapter`` +------------------------------ + +This class is used to build custom pointer containers with +an underlying multiset-like container. The interface of the class is an extension +of the interface from ``associative_ptr_container``. + +**See also:** + +- reversible_ptr_container_ +- associative_ptr_container_ +- ptr_multiset_ + +.. _reversible_ptr_container: reversible_ptr_container.html +.. _associative_ptr_container: associative_ptr_container.html +.. _ptr_multiset: ptr_multiset.html + +**Navigate:** + +- `home `_ +- `reference `_ + +**Synopsis:** + +.. parsed-literal:: + + + namespace boost + { + template + < + class Key, + class VoidPtrMultiSet, + class CloneAllocator = heap_clone_allocator + > + class ptr_multiset_adapter + { + + public: // `modifiers`_ + iterator insert( Key* x ); + + public: // `pointer container requirements`_ + void transfer( iterator object, ptr_multiset_adapter& from ); + size_type transfer( iterator first, iterator last, ptr_multiset_adapter& from ); + template< class Range > + size_type transfer( const Range& r, ptr_multiset_adapter& from ); + void transfer( ptr_multiset_adapter& from ); + + }; // class 'ptr_multiset_adapter' + + } // namespace 'boost' + + +Semantics +--------- + +.. _`modifiers`: + +Semantics: modifiers +^^^^^^^^^^^^^^^^^^^^ + +- ``iterator insert( key_type* x );`` + + - Requirements: ``x != 0`` + + - Effects: Takes ownership of ``x``. The returned iterator points to the element with key ``x``. + + - Throws: bad_pointer if ``x == 0`` + + - Exception safety: Strong guarantee + +.. + - ``iterator insert( const key_type& x );`` + + - Effects: ``return insert( allocate_clone( x ) );`` + + - Exception safety: Strong guarantee + +.. _`pointer container requirements`: + +Semantics: pointer container requirements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- ``void transfer( iterator object, ptr_multiset_adapter& from );`` + + - Requirements: ``not from.empty()`` + + - Effects: Inserts the object defined by ``object`` into the container and remove it from ``from``. + + - Postconditions: ``size()`` is one more, ``from.size()`` is one less. + + - Exception safety: Strong guarantee + +- ``void transfer( iterator first, iterator last, ptr_multiset_adapter& from );`` + + - Requirements: ``not from.empty()`` + + - Effects: Inserts the objects defined by the range ``[first,last)`` into the container and remove it from ``from``. + + - Postconditions: Let ``N == std::distance(first,last);`` then ``size()`` is ``N`` more, ``from.size()`` is ``N`` less. + + - Exception safety: Basic guarantee + +- ``template< class Range > void transfer( const Range& r, ptr_multiset_adapter& from );`` + + - Effects: ``transfer( boost::begin(r), boost::end(r), from );`` + +- ``void transfer( ptr_multiset_adapter& from );`` + + - Effects: ``transfer( from.begin(), from.end(), from );``. + + - Postconditions: ``from.empty();`` + + - Exception safety: Basic guarantee + + diff --git a/doc/ptr_sequence_adapter.html b/doc/ptr_sequence_adapter.html new file mode 100644 index 0000000..88a4712 --- /dev/null +++ b/doc/ptr_sequence_adapter.html @@ -0,0 +1,328 @@ + + + + + + + + + + +
+
+

Class ptr_sequence_adapter

+

This section describes all the common operations for all the pointer +sequences:

+ +

The ptr_sequence_adapter is also a concrete class that you can use to create custom pointer +containers from.

+

See also:

+ +

Navigate:

+ +

Synopsis:

+
+namespace boost
+{      
+
+    template
+    < 
+        class T, 
+        class VoidPtrSeq,
+        class CloneAllocator = heap_clone_allocator
+    >
+    class ptr_sequence_adapter 
+    {
+    public: // construct/copy/destroy
+        template< class InputIterator >
+        assign( InputIterator first, InputIterator last );
+        template< class InputRange >
+        assign( const InputRange& e );
+    
+    public: // element access
+        T&        front();
+        const T&  front() const;
+        T&        back();
+        const T&  back() const;
+    
+    public: // modifiers
+        void      push_back( T* x );
+        auto_type pop_back();
+        iterator  insert( iterator position, T* x );
+        template< class InputIterator >
+        void      insert( iterator position, InputIterator first, InputIterator last ); 
+        template< class InputRange >
+        void      insert( iterator position, const InputRange& r );
+        iterator  erase( iterator position );
+        iterator  erase( iterator first, iterator last );
+        template< class Range >
+        iterator  erase( const Range& r );
+    
+    public: // pointer container requirements
+
+        void  transfer( iterator before, iterator object, 
+                        ptr_sequence_adapter& from );
+        void  transfer( iterator before, iterator first, iterator last,
+                        ptr_sequence_adapter& from );
+        void template< class Range> 
+        void transfer( iterator before, const Range& r, ptr_sequence_adapter& from );
+        void transfer( iterator before, ptr_sequence_adapter& from );
+
+     public: // ptr_list interface
+     
+     public: // ptr_vector interface
+
+     public: // ptr_deque interface 
+     
+    }; //  class 'ptr_sequence_adapter'
+
+} // namespace 'boost'  
+
+
+
+

Semantics

+
+

Semantics: construct/copy/destroy

+
    +
  • template< class InputIterator > +void assign( InputIterator first, InputIterator last );

    +
    +
      +
    • Requirements: (first,last] is a valid range
    • +
    • Effects: clear(); insert( first, last );
    • +
    • Postconditions: size() == std::distance( first, last );
    • +
    • Exception safety: strong guarantee
    • +
    +
    +
  • +
  • template< class InputRange > +void assign( const InputRange& r );

    +
    +
      +
    • Effects: assign( boost::begin(r), boost::end(r) );
    • +
    +
    +
  • +
+ + +
+
+

Semantics: element access

+
    +
  • T& front();

    +
    +
      +
    • Requirements: not empty();
    • +
    • Effects: return *begin();
    • +
    • Throws: bad_ptr_container_operation if empty() == true
    • +
    +
    +
  • +
  • const T& front() const;

    +
    +
      +
    • Requirements: not empty();
    • +
    • Effects: return *begin();
    • +
    • Throws: bad_ptr_container_operation if empty() == true
    • +
    +
    +
  • +
  • T& back();

    +
    +
      +
    • Requirements: not empty();
    • +
    • Effects: return *--end();
    • +
    • Throws: bad_ptr_container_operation if empty() == true
    • +
    +
    +
  • +
  • const T& back() const;

    +
    +
      +
    • Requirements: not empty();
    • +
    • Effects: return *--end();
    • +
    • Throws: bad_ptr_container_operation if empty() == true
    • +
    +
    +
  • +
+
+
+

Semantics: modifiers

+
    +
  • void push_back( T* x );

    +
    +
      +
    • Requirements: x != 0
    • +
    • Effects: Inserts the pointer into container and takes ownership of it
    • +
    • Throws: bad_pointer if x == 0
    • +
    • Exception safety: Strong guarantee
    • +
    +
    +
  • +
+ +
    +
  • auto_type pop_back();

    +
    +
      +
    • Requirements:not empty()
    • +
    • Effects: Removes the last element in the container
    • +
    • Postconditions: size() is one less
    • +
    • Throws: bad_ptr_container_operation if empty() == true
    • +
    • Exception safety: Strong guarantee
    • +
    +
    +
  • +
  • iterator insert( iterator position, T* x );

    +
    +
      +
    • Requirements: position is a valid iterator from the container and +x != 0
    • +
    • Effects: Inserts x before position and returns an iterator pointing to it
    • +
    • Throws: bad_pointer if x == 0
    • +
    • Exception safety: Strong guarantee
    • +
    +
    +
  • +
+ +
    +
  • template< class InputIterator > +void insert( iterator position, InputIterator first, InputIterator last );

    +
    +
      +
    • Requirements: position is a valid iterator from the container
    • +
    • Effects: Inserts a cloned range before position
    • +
    • Exception safety: Strong guarantee
    • +
    +
    +
  • +
  • template< class InputRange > +void insert( iterator position, const InputRange& r );

    +
    +
      +
    • Effects: insert( position, boost::begin(r), boost::end(r) );
    • +
    +
    +
  • +
  • iterator erase( iterator position );

    +
    +
      +
    • Requirements: position is a valid iterator from the container
    • +
    • Effects: Removes the element defined by position and returns an iterator to the following element
    • +
    • Throws: Nothing
    • +
    +
    +
  • +
  • iterator erase( iterator first, iterator last );

    +
    +
      +
    • Requirements: [first,last) is a valid range
    • +
    • Effects: Removes the range of element defined by [first,last) and returns an iterator to the following element
    • +
    • Throws: Nothing
    • +
    +
    +
  • +
  • template< class Range > +void erase( const Range& r );

    +
    +
      +
    • Effects: erase( boost::begin(r), boost::end(r) );
    • +
    +
    +
  • +
+
+
+

Semantics: pointer container requirements

+
    +
  • void transfer( iterator before, iterator object, ptr_sequence_adapter& from );

    +
    +
      +
    • Requirements: not from.empty()
    • +
    • Effects: Inserts the object defined by object into the container and remove it from from.
    • +
    • Postconditions: size() is one more, from.size() is one less.
    • +
    • Exception safety: Strong guarantee
    • +
    +
    +
  • +
  • void transfer( iterator before, iterator first, iterator last, ptr_sequence_adapter& from );

    +
    +
      +
    • Requirements: not from.empty()
    • +
    • Effects: Inserts the objects defined by the range [first,last) into the container and remove it from from.
    • +
    • Postconditions: Let N == std::distance(first,last); then size() is N more, from.size() is N less.
    • +
    • Exception safety: Strong guarantee
    • +
    +
    +
  • +
  • template< class Range> void transfer( iterator before, const Range& r, ptr_sequence_adapter& from );

    +
    +
      +
    • Effects: transfer(before, boost::begin(r), boost::end(r), from);
    • +
    +
    +
  • +
  • void transfer( iterator before, ptr_sequence_adapter& from );

    +
    +
      +
    • Effects: Transfers all objects from from into the container. Insertion +takes place before before.
    • +
    • Postconditions: from.empty();
    • +
    • Exception safety: Strong guarantee
    • +
    +
    +
  • +
+
+
+
+ + diff --git a/doc/ptr_sequence_adapter.rst b/doc/ptr_sequence_adapter.rst new file mode 100755 index 0000000..e5ea94e --- /dev/null +++ b/doc/ptr_sequence_adapter.rst @@ -0,0 +1,323 @@ + +Class ``ptr_sequence_adapter`` +------------------------------ + +This section describes all the common operations for all the pointer +sequences: + +- ptr_vector_, +- ptr_list_, +- ptr_deque_, + +.. _ptr_vector : ptr_vector.html +.. _ptr_list : ptr_list.html +.. _ptr_deque : ptr_deque.html + + +The ``ptr_sequence_adapter`` is also a concrete class that you can use to create custom pointer +containers from. + +**See also:** + +- reversible_ptr_container__ + +__ reversible_ptr_container.html + +**Navigate:** + +- `home `_ +- `reference `_ + + +**Synopsis:** + +.. parsed-literal:: + + namespace boost + { + + template + < + class T, + class VoidPtrSeq, + class CloneAllocator = heap_clone_allocator + > + class ptr_sequence_adapter + { + public: // `construct/copy/destroy`_ + template< class InputIterator > + assign( InputIterator first, InputIterator last ); + template< class InputRange > + assign( const InputRange& e ); + + public: // `element access`_ + T& front(); + const T& front() const; + T& back(); + const T& back() const; + + public: // `modifiers`_ + void push_back( T* x ); + auto_type pop_back(); + iterator insert( iterator position, T* x ); + template< class InputIterator > + void insert( iterator position, InputIterator first, InputIterator last ); + template< class InputRange > + void insert( iterator position, const InputRange& r ); + iterator erase( iterator position ); + iterator erase( iterator first, iterator last ); + template< class Range > + iterator erase( const Range& r ); + + public: // `pointer container requirements`_ + + void transfer( iterator before, iterator object, + ptr_sequence_adapter& from ); + void transfer( iterator before, iterator first, iterator last, + ptr_sequence_adapter& from ); + void template< class Range> + void transfer( iterator before, const Range& r, ptr_sequence_adapter& from ); + void transfer( iterator before, ptr_sequence_adapter& from ); + + public: // `ptr_list interface`_ + + public: // `ptr_vector interface`_ + + public: // `ptr_deque interface`_ + + }; // class 'ptr_sequence_adapter' + + } // namespace 'boost' + +.. _`ptr_list interface`: ptr_list.html +.. _`ptr_vector interface`: ptr_vector.html +.. _`ptr_deque interface`: ptr_deque.html + +Semantics +--------- + +.. _`construct/copy/destroy`: + +Semantics: construct/copy/destroy +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- ``template< class InputIterator > + void assign( InputIterator first, InputIterator last );`` + + - Requirements: ``(first,last]`` is a valid range + + - Effects: ``clear(); insert( first, last );`` + + - Postconditions: ``size() == std::distance( first, last );`` + + - Exception safety: strong guarantee + +- ``template< class InputRange > + void assign( const InputRange& r );`` + + - Effects: ``assign( boost::begin(r), boost::end(r) );`` + + +.. + - ``assign( size_type n, const T& u )`` + + - Effects: ``clear(); insert( begin(), n, u );`` + + - Postconditions: ``size() == n`` + + - Exception safety: Strong guarantee + + +.. + void resize( size_type sz, const T& x ); + Effects: + + if ( sz > size() ) + insert( end(), sz-size(), x ); + else if ( sz < size() ) + erase( begin()+sz, end() ); + else + ; //do nothing + + Postconditions: size() == sz + + Exception safety: Strong guarantee + + +.. _`element access`: + +Semantics: element access +^^^^^^^^^^^^^^^^^^^^^^^^^ + +- ``T& front();`` + + - Requirements: ``not empty();`` + + - Effects: ``return *begin();`` + + - Throws: ``bad_ptr_container_operation`` if ``empty() == true`` + +- ``const T& front() const;`` + + - Requirements: ``not empty();`` + + - Effects: ``return *begin();`` + + - Throws: ``bad_ptr_container_operation`` if ``empty() == true`` + +- ``T& back();`` + + - Requirements: ``not empty();`` + + - Effects: ``return *--end();`` + + - Throws: ``bad_ptr_container_operation`` if ``empty() == true`` + +- ``const T& back() const;`` + + - Requirements: ``not empty();`` + + - Effects: ``return *--end();`` + + - Throws: ``bad_ptr_container_operation`` if ``empty() == true`` + + +.. _`modifiers`: + +Semantics: modifiers +^^^^^^^^^^^^^^^^^^^^ + +- ``void push_back( T* x );`` + + - Requirements: ``x != 0`` + + - Effects: Inserts the pointer into container and takes ownership of it + + - Throws: ``bad_pointer`` if ``x == 0`` + + - Exception safety: Strong guarantee + +.. + - ``void push_back( const T& x );`` + + - Effects: ``push_back( CloneAllocator::clone( x ) );`` + + - Exception safety: Strong guarantee + +- ``auto_type pop_back();`` + + - Requirements:``not empty()`` + + - Effects: Removes the last element in the container + + - Postconditions: ``size()`` is one less + + - Throws: ``bad_ptr_container_operation`` if ``empty() == true`` + + - Exception safety: Strong guarantee + + +- ``iterator insert( iterator position, T* x );`` + + - Requirements: position is a valid iterator from the container and + ``x != 0`` + + - Effects: Inserts ``x`` before position and returns an iterator pointing to it + + - Throws: ``bad_pointer`` if ``x == 0`` + + - Exception safety: Strong guarantee + +.. + - ``iterator insert( iterator position, const T& x );`` + + - Requirements: ``position`` is a valid iterator from the container + + - Effects: ``return insert( position, CloneAllocator::clone( x ) );`` + + - Exception safety: Strong guarantee + + - ``void insert( iterator position, size_type n, const T& x );`` + + - Requirements: ``position`` is a valid iterator from the container + + - Effects: Inserts ``n`` clones of ``x`` before position into the container + + - Exception safety: Strong guarantee + +- ``template< class InputIterator > + void insert( iterator position, InputIterator first, InputIterator last );`` + + - Requirements: ``position`` is a valid iterator from the container + + - Effects: Inserts a cloned range before ``position`` + + - Exception safety: Strong guarantee + +- ``template< class InputRange > + void insert( iterator position, const InputRange& r );`` + + - Effects: ``insert( position, boost::begin(r), boost::end(r) );`` + +- ``iterator erase( iterator position );`` + + - Requirements: ``position`` is a valid iterator from the container + + - Effects: Removes the element defined by ``position`` and returns an iterator to the following element + + - Throws: Nothing + +- ``iterator erase( iterator first, iterator last );`` + + - Requirements: ``[first,last)`` is a valid range + + - Effects: Removes the range of element defined by ``[first,last)`` and returns an iterator to the following element + + - Throws: Nothing + +- ``template< class Range > + void erase( const Range& r );`` + + - Effects: ``erase( boost::begin(r), boost::end(r) );`` + +.. _`pointer container requirements`: + +Semantics: pointer container requirements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- ``void transfer( iterator before, iterator object, ptr_sequence_adapter& from );`` + + - Requirements: ``not from.empty()`` + + - Effects: Inserts the object defined by ``object`` into the container and remove it from ``from``. + + - Postconditions: ``size()`` is one more, ``from.size()`` is one less. + + - Exception safety: Strong guarantee + +- ``void transfer( iterator before, iterator first, iterator last, ptr_sequence_adapter& from );`` + + - Requirements: ``not from.empty()`` + + - Effects: Inserts the objects defined by the range ``[first,last)`` into the container and remove it from ``from``. + + - Postconditions: Let ``N == std::distance(first,last);`` then ``size()`` is ``N`` more, ``from.size()`` is ``N`` less. + + - Exception safety: Strong guarantee + +- ``template< class Range> void transfer( iterator before, const Range& r, ptr_sequence_adapter& from );`` + + - Effects: ``transfer(before, boost::begin(r), boost::end(r), from);`` + +- ``void transfer( iterator before, ptr_sequence_adapter& from );`` + + - Effects: Transfers all objects from ``from`` into the container. Insertion + takes place before ``before``. + + - Postconditions: ``from.empty();`` + + - Exception safety: Strong guarantee + + + + diff --git a/doc/ptr_set.html b/doc/ptr_set.html new file mode 100644 index 0000000..b4f89b9 --- /dev/null +++ b/doc/ptr_set.html @@ -0,0 +1,59 @@ + + + + + + +Class ptr_set + + + +
+

Class ptr_set

+

A ptr_set<T> is a pointer container that uses an underlying std::set<void*> +to store the pointers.

+

See also:

+ +

Navigate:

+ +

Synopsis:

+
+namespace boost
+{
+
+    template
+    < 
+        class Key, 
+        class Compare        = std::less<Key>, 
+        class CloneAllocator = heap_clone_allocator, 
+        class Allocator      = std::allocator<void*>
+    >
+    class ptr_set : public  ptr_set_adapter
+                            <
+                                Key,
+                                std::set<void*,
+                                void_ptr_indirect_fun<Compare,Key>,Allocator>,
+                                CloneAllocator
+                            >
+    {
+        // see references
+        
+    }; //  class 'ptr_set'
+
+} // namespace 'boost'  
+
+

Remarks:

+
    +
  • Using nullable<T> as Key is meaningless and not allowed
  • +
+
+ + diff --git a/doc/ptr_set.rst b/doc/ptr_set.rst new file mode 100755 index 0000000..4da8e14 --- /dev/null +++ b/doc/ptr_set.rst @@ -0,0 +1,55 @@ +Class ``ptr_set`` +----------------- + +A ``ptr_set`` is a pointer container that uses an underlying ``std::set`` +to store the pointers. + +**See also:** + +- reversible_ptr_container_ +- associative_ptr_container_ +- ptr_set_adapter_ +- `void_ptr_indirect_fun `_ + +.. _reversible_ptr_container: reversible_ptr_container.html +.. _associative_ptr_container: associative_ptr_container.html +.. _ptr_set_adapter: ptr_set_adapter.html + +**Navigate:** + +- `home `_ +- `reference `_ + + +**Synopsis:** + +.. parsed-literal:: + + + namespace boost + { + + template + < + class Key, + class Compare = std::less, + class CloneAllocator = heap_clone_allocator, + class Allocator = std::allocator + > + class ptr_set : public ptr_set_adapter + < + Key, + std::set,Allocator>, + CloneAllocator + > + { + // see references + + }; // class 'ptr_set' + + } // namespace 'boost' + +**Remarks:** + +- Using ``nullable`` as ``Key`` is meaningless and not allowed diff --git a/doc/ptr_set_adapter.html b/doc/ptr_set_adapter.html new file mode 100644 index 0000000..d689342 --- /dev/null +++ b/doc/ptr_set_adapter.html @@ -0,0 +1,122 @@ + + + + + + + + + + +
+
+

Class ptr_set_adapter

+

This class is used to build custom pointer containers with +an underlying set-like container. The interface of the class is an extension +of the interface from associative_ptr_container.

+

See also:

+ +

Navigate:

+ +

Synopsis:

+
+namespace boost
+{
+    template
+    < 
+        class Key, 
+        class VoidPtrSet,
+        class CloneAllocator = heap_clone_allocator 
+    >
+    class ptr_set_adapter 
+    {
+        
+    public: // modifiers         
+        std::pair<iterator,bool>  insert( Key* x );                         
+
+    public: // pointer container requirements
+        bool      transfer( iterator object, ptr_set_adapter& from );
+        size_type transfer( iterator first, iterator last, ptr_set_adapter& from );
+        template< class Range >
+        size_type transfer( const Range& r, ptr_set_adapter& from );
+        size_type transfer( ptr_set_adapter& from );
+
+    }; //  class 'ptr_set_adapter'
+
+} // namespace 'boost'  
+
+
+
+

Semantics

+
+

Semantics: modifiers

+
    +
  • std::pair<iterator,bool> insert( key_type* x );

    +
    +
      +
    • Requirements: x != 0
    • +
    • Effects: Takes ownership of x and insert it if there is no equivalent of it already. The bool part of the return value indicates insertion and the iterator points to the element with key x.
    • +
    • Throws: bad_pointer if x == 0
    • +
    • Exception safety: Strong guarantee
    • +
    +
    +
  • +
+ +
+
+

Semantics: pointer container requirements

+
    +
  • bool transfer( iterator object, ptr_set_adapter& from );

    +
    +
      +
    • Requirements: not from.empty()
    • +
    • Effects: Inserts the object defined by object into the container and remove it from from +iff no equivalent object exists.
    • +
    • Returns: whether the object was transfered
    • +
    • Exception safety: Strong guarantee
    • +
    +
    +
  • +
  • void transfer( iterator first, iterator last, ptr__set_adapter& from );

    +
    +
      +
    • Requirements: not from.empty()
    • +
    • Effects: Inserts the objects defined by the range [first,last) into the container and remove it from from. +An object is only transferred if no equivalent object exists.
    • +
    • Returns: the number of transfered objects
    • +
    • Exception safety: Basic guarantee
    • +
    +
    +
  • +
  • template< class Range > void transfer( const Range& r, ptr_set_adapter& from );

    +
    +
      +
    • Effects: return transfer( boost::begin(r), boost::end(r), from );
    • +
    +
    +
  • +
  • size_type transfer( ptr_set_adapter& from );

    +
    +
      +
    • Effects: return transfer( from.begin(), from.end(), from );.
    • +
    +
    +
  • +
+
+
+
+ + diff --git a/doc/ptr_set_adapter.rst b/doc/ptr_set_adapter.rst new file mode 100755 index 0000000..bc52da2 --- /dev/null +++ b/doc/ptr_set_adapter.rst @@ -0,0 +1,115 @@ +Class ``ptr_set_adapter`` +------------------------- + +This class is used to build custom pointer containers with +an underlying set-like container. The interface of the class is an extension +of the interface from ``associative_ptr_container``. + +**See also:** + +- reversible_ptr_container_ +- associative_ptr_container_ +- ptr_set_ + +**Navigate:** + +- `home `_ +- `reference `_ + +.. _reversible_ptr_container: reversible_ptr_container.html +.. _associative_ptr_container: associative_ptr_container.html +.. _ptr_set: ptr_set.html + +**Synopsis:** + +.. parsed-literal:: + + + namespace boost + { + template + < + class Key, + class VoidPtrSet, + class CloneAllocator = heap_clone_allocator + > + class ptr_set_adapter + { + + public: // `modifiers`_ + std::pair insert( Key* x ); + + public: // `pointer container requirements`_ + bool transfer( iterator object, ptr_set_adapter& from ); + size_type transfer( iterator first, iterator last, ptr_set_adapter& from ); + template< class Range > + size_type transfer( const Range& r, ptr_set_adapter& from ); + size_type transfer( ptr_set_adapter& from ); + + }; // class 'ptr_set_adapter' + + } // namespace 'boost' + + +Semantics +--------- + +.. _`modifiers`: + +Semantics: modifiers +^^^^^^^^^^^^^^^^^^^^ + +- ``std::pair insert( key_type* x );`` + + - Requirements: ``x != 0`` + + - Effects: Takes ownership of ``x`` and insert it if there is no equivalent of it already. The ``bool`` part of the return value indicates insertion and the iterator points to the element with key ``x``. + + - Throws: bad_pointer if ``x == 0`` + + - Exception safety: Strong guarantee + +.. + - ``std::pair insert( const key_type& x );`` + + - Effects: ``return insert( allocate_clone( x ) );`` + + - Exception safety: Strong guarantee + +.. _`pointer container requirements`: + +Semantics: pointer container requirements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- ``bool transfer( iterator object, ptr_set_adapter& from );`` + + - Requirements: ``not from.empty()`` + + - Effects: Inserts the object defined by ``object`` into the container and remove it from ``from`` + iff no equivalent object exists. + + - Returns: whether the object was transfered + + - Exception safety: Strong guarantee + +- ``void transfer( iterator first, iterator last, ptr__set_adapter& from );`` + + - Requirements: ``not from.empty()`` + + - Effects: Inserts the objects defined by the range ``[first,last)`` into the container and remove it from ``from``. + An object is only transferred if no equivalent object exists. + + - Returns: the number of transfered objects + + - Exception safety: Basic guarantee + +- ``template< class Range > void transfer( const Range& r, ptr_set_adapter& from );`` + + - Effects: ``return transfer( boost::begin(r), boost::end(r), from );`` + +- ``size_type transfer( ptr_set_adapter& from );`` + + - Effects: ``return transfer( from.begin(), from.end(), from );``. + + + diff --git a/doc/ptr_vector.html b/doc/ptr_vector.html new file mode 100644 index 0000000..acefcab --- /dev/null +++ b/doc/ptr_vector.html @@ -0,0 +1,158 @@ + + + + + + + + + + +
+
+

Class ptr_vector

+

A ptr_vector<T> is a pointer container that uses an underlying std::vector<void*> +to store the pointers.

+

See also:

+ +

Navigate:

+ +

Synopsis:

+
+namespace boost
+{      
+
+    template
+    < 
+        class T, 
+        class CloneAllocator = heap_clone_allocator,
+        class Allocator      = std::allocator<void*>
+    >
+    class ptr_vector : public ptr_sequence_adapter
+                              <
+                                  T,
+                                  std::vector<void*,Allocator>,
+                                  CloneAllocator
+                              >
+    {
+    public: // construction
+        ptr_vector( size_type to_reserve );
+    
+    public: // capacity
+        size_type  capacity() const;
+        void       reserve( size_type n );
+    
+    public: // element access
+        T&        operator[]( size_type n );
+        const T&  operator[]( size_type n ) const;
+        T&        at( size_type n );
+        const T&  at( size_type n ) const;
+
+    public: // pointer container requirements
+       auto_type replace( size_type idx, T* x );    
+       bool      is_null( size_type idx ) const;
+    };
+   
+} // namespace 'boost'  
+
+
+
+

Semantics

+
+

Semantics: construction

+
    +
  • ptr_vector( size_type to_reserve );

    +
    +
      +
    • constructs an empty vector with a buffer +of size least to_reserve
    • +
    +
    +
  • +
+
+
+

Semantics: capacity

+
    +
  • size_type capacity() const;

    +
    +
      +
    • Effects: Returns the size of the allocated buffer
    • +
    • Throws: Nothing
    • +
    +
    +
  • +
  • void reserve( size_type n );

    +
    +
      +
    • Requirements: n <= max_size()
    • +
    • Effects: Expands the allocated buffer
    • +
    • Postcondition: capacity() >= n
    • +
    • Throws: std::length_error() if n > max_size()
    • +
    +
    +
  • +
+
+
+

Semantics: element access

+
    +
  • T& operator[]( size_type n );

    +
  • +
  • const T& operator[]( size_type n ) const;

    +
    +
      +
    • Requirements: n < size()
    • +
    • Effects: Returns a reference to the n'th element
    • +
    • Throws: Nothing
    • +
    +
    +
  • +
  • T& at( size_type n );

    +
  • +
  • const T& at( size_type n ) const;

    +
    +
      +
    • Requirements: n < size()
    • +
    • Effects: Returns a reference to the n'th element
    • +
    • Throws: bad_index if n >=size()
    • +
    +
    +
  • +
+
+
+

Semantics: pointer container requirements

+
    +
  • auto_type replace( size_type idx, T* x );

    +
    +
      +
    • Requirements: `` x != 0 and idx < size()``
    • +
    • Effects: returns the object indexed by idx and replaces it with x.
    • +
    • Throws: bad_index if idx >= size() and bad_pointer if x == 0.
    • +
    • Exception safety: Strong guarantee
    • +
    +
    +
  • +
  • bool is_null( size_type idx ) const;

    +
    +
      +
    • Requirements: idx < size()
    • +
    • Effects: returns whether the pointer at index idx is null
    • +
    • Exception safety: Nothrow guarantee
    • +
    +
    +
  • +
+
+
+
+ + diff --git a/doc/ptr_vector.rst b/doc/ptr_vector.rst new file mode 100755 index 0000000..2e64828 --- /dev/null +++ b/doc/ptr_vector.rst @@ -0,0 +1,144 @@ +Class ``ptr_vector`` +-------------------- + +A ``ptr_vector`` is a pointer container that uses an underlying ``std::vector`` +to store the pointers. + +**See also:** + +- reversible_ptr_container_ +- ptr_sequence_adapter_ +- ptr_array_ + +.. _reversible_ptr_container: reversible_ptr_container.html +.. _ptr_sequence_adapter: ptr_sequence_adapter.html +.. _ptr_array: ptr_array.html + +**Navigate:** + +- `home `_ +- `reference `_ + +**Synopsis:** + +.. parsed-literal:: + + namespace boost + { + + template + < + class T, + class CloneAllocator = heap_clone_allocator, + class Allocator = std::allocator + > + class ptr_vector : public ptr_sequence_adapter + < + T, + std::vector, + CloneAllocator + > + { + public: // `construction`_ + ptr_vector( size_type to_reserve ); + + public: // capacity_ + size_type capacity() const; + void reserve( size_type n ); + + public: // `element access`_ + T& operator[]( size_type n ); + const T& operator[]( size_type n ) const; + T& at( size_type n ); + const T& at( size_type n ) const; + + public: // `pointer container requirements`_ + auto_type replace( size_type idx, T* x ); + bool is_null( size_type idx ) const; + }; + + } // namespace 'boost' + + +Semantics +--------- + +.. _`construction`: + +Semantics: construction +^^^^^^^^^^^^^^^^^^^^^^^ + +- ``ptr_vector( size_type to_reserve );`` + + - constructs an empty vector with a buffer + of size least ``to_reserve`` + +.. _`capacity`: + +Semantics: capacity +^^^^^^^^^^^^^^^^^^^ + +- ``size_type capacity() const;`` + + - Effects: Returns the size of the allocated buffer + + - Throws: Nothing + +- ``void reserve( size_type n );`` + + - Requirements: ``n <= max_size()`` + + - Effects: Expands the allocated buffer + + - Postcondition: ``capacity() >= n`` + + - Throws: ``std::length_error()`` if ``n > max_size()`` + + +.. _`element access`: + +Semantics: element access +^^^^^^^^^^^^^^^^^^^^^^^^^ + +- ``T& operator[]( size_type n );`` +- ``const T& operator[]( size_type n ) const;`` + + - Requirements: ``n < size()`` + + - Effects: Returns a reference to the ``n``'th element + + - Throws: Nothing + +- ``T& at( size_type n );`` +- ``const T& at( size_type n ) const;`` + + - Requirements: ``n < size()`` + + - Effects: Returns a reference to the ``n``'th element + + - Throws: ``bad_index`` if ``n >=size()`` + + +.. _`pointer container requirements`: + +Semantics: pointer container requirements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- ``auto_type replace( size_type idx, T* x );`` + + - Requirements: `` x != 0 and idx < size()`` + + - Effects: returns the object indexed by ``idx`` and replaces it with ``x``. + + - Throws: ``bad_index`` if ``idx >= size()`` and ``bad_pointer`` if ``x == 0``. + + - Exception safety: Strong guarantee + +- ``bool is_null( size_type idx ) const;`` + + - Requirements: ``idx < size()`` + + - Effects: returns whether the pointer at index ``idx`` is null + + - Exception safety: Nothrow guarantee + diff --git a/doc/reference.html b/doc/reference.html new file mode 100644 index 0000000..662d8a7 --- /dev/null +++ b/doc/reference.html @@ -0,0 +1,389 @@ + + + + + + +Reference + + + +
+

Reference

+

The documentation is divided into a an explanation for +each container. All the common interface is explained only once, +but links are always provided to the relevant links. +Please make sure you understand +the Clonable concept and +the Clone Allocator concept.

+ +
+

The Clonable concept

+

Refinement of

+
    +
  • Copy Constructible
  • +
  • Heap Allocable
  • +
  • Heap Deallocable
  • +
+

The Clonable concept is introduced to formalize the requirements for +copying heap-allocated objects. A type T might be Clonable even though it +is not Assignable or Copy Constructible. Notice that many operations on +the containers does not even require the stored type to be Clonable.

+

Notation

+ ++++++ + + + + + + + + + + + + +
TypeObject (const or non-const)PointerDescribes
TaptrA Clonable type
+

Valid expressions

+ +++++ + + + + + + + + + + + + + + +
ExpressionTypeSemantics
new_clone(a);T*Allocate a new object that can be considered equivalent to the a object
delete_clone(ptr);voidDeallocate an object previously allocated with allocate_clone(). Must not throw
+
+

Default implementation

+

In the <boost/ptr_container/heap_manager.hpp> header a default implementation +of the two functions is given:

+
+namespace boost
+{
+    template< class T >
+    inline T* new_clone( const T& t )
+    {
+        return new T( t );
+    }
+
+    template< class T >
+    void delete_clone( const T* t )
+    {
+        checked_delete( r );
+    }
+}
+
+

Notice that this implementation makes normal Copy Constructible classes are automatically +Clonable unless operator new() or operator delete() are hidden.

+

The two functions represent a layer of indirection which is necessary to support +classes that are not Copy Constructible by default. Notice that the implementation +relies on argument-dependent lookup (ADL) to find the right version of +new_clone() and delete_clone(). This means that one does not need to overload or specialize +the function is the boost namespace, but it can be placed together with +the rest of the interface of the class. If you are implementing a class +inline in headers, remember to forward declare the functions.

+
+
+
+

The Clone Allocator concept

+

The Clone Allocator concept is introduced to formalize the way +pointer containers controls memory of +the stored objects (and not the pointers to the stored objects). +The clone allocator allows +users to apply custom allocators/deallocators for the cloned objects.

+

More information can be found below:

+ +
+

Clone Allocator requirements

+

Notation

+ +++++ + + + + + + + + + + + + + + +
TypeObject (const or non-const)Describes
TaA type
T*ptrA pointer to T
+

Valid expressions

+ +++++ + + + + + + + + + + + + + + +
ExpressionTypeSemantics
CloneAllocator::allocate_clone(a);T*Allocate a new object that can be considered equivalent to the a object
CloneAllocator::deallocate_clone(ptr);voidDeallocate an object previously allocated with CloneAllocator::allocate_clone() or a compatible allocator. Must not throw.
+

The library comes with two predefined clone allocators.

+
+
+

Class heap_clone_allocator

+

This is the default clone allocator used by all pointer containers. For most +purposes you will never have to change this default.

+

Definition

+
+namespace boost
+{        
+    struct heap_clone_allocator
+    {
+        template< class U >
+        static U* allocate_clone( const U& r )
+        {
+            return new_clone( r );
+        }
+
+        template< class U >
+        static void deallocate_clone( const U* r ) const
+        {
+            delete_clone( r );
+        }
+    };
+}
+
+

Notice that the above definition allows you to support custom allocation +schemes by relying on new_clone() and delete_clone().

+
+
+

Class view_clone_allocator

+

This class provides a way to remove ownership properties of the +pointer containers. As its name implies, this means that you can +instead use the pointer containers as a view into an existing +container.

+

Definition

+
+namespace boost
+{
+    struct view_clone_allocator
+    {
+        template< class U >
+        static U* allocate_clone( const U& r )
+        {
+            return const_cast<U*>(&r);
+        }
+
+        template< class U >
+        static void deallocate_clone( const U* )
+        {
+            // empty
+        }
+    };
+}
+
+

See also

+ +
+
+
+

Pointer container adapters

+

The pointer container adapters are used when you +want to make a pointer container starting from +your own "normal" container. For example, you +might have a map class that is extends std::map +in some way; the adapter class then allows you +to use your map class as a basis for a new +pointer container.

+

The library provides an adapter for each type +of standard container:

+ +
+
+

Pointer containers

+

The pointer containers of this library are all built using +the pointer container adapters. There is a pointer container +for each type of "normal" standard container:

+ + +
+
+

Map iterator operations

+

The map iterators are a bit different compared to the normal ones. The +reason is that it is a bit clumsy to access the key and the mapped object +through i->first and i->second, and one tends to forget what is what. +Moreover, and more importantly, we also want to hide the pointer as much as possibble. +The new style can be illustrated with a small example:

+
+typedef ptr_map<string,int> map_t;
+map_t  m;
+m[ "foo" ] = 4; // insert pair
+m[ "bar" ] = 5; // ditto
+...
+for( map_t::iterator i = m.begin(); i != m.end(); ++i )
+{
+         *i += 42; // add 42 to each value
+         cout << "value=" << *i << ", key=" << i.key() << "n";
+} 
+
+

So the difference from the normal map iterator is that

+
    +
  • operator*() returns a reference to the mapped object (normally it returns a reference to a std::pair, and
  • +
  • that the key can be accessed through the key() function.
  • +
+
+
+

Class nullable

+

The purpose of the class is simply to tell the containers +that null values should be allowed. Its definition is +trivial:

+
+namespace boost
+{
+    template< class T >
+    struct nullable
+    {
+        typedef T type;
+    };  
+}
+
+

Please notice that nullable has no effect on the containers +interface (except for is_null() functions). For example, it +does not make sense to do

+
+boost::ptr_vector< boost::nullable<T> > vec;
+vec.push_back( new boost::nullable<T> ); // no no
+boost::nullable<T>& ref = vec[0];        // also no no
+
+
+
+

Exception classes

+

There are three exceptions that are thrown by this library. The exception +hierarchy looks as follows:

+
+namespace boost
+{
+    class bad_ptr_container_operation : public std::exception
+    {
+    public:
+        bad_ptr_container_operation( const char* what );
+    };
+    
+    class bad_index : public bad_ptr_container_operation
+    {
+    public:
+        bad_index( const char* what );
+    };
+
+    class bad_pointer : public bad_ptr_container_operation
+    {
+    public:
+        bad_pointer();
+        bad_pointer( const char* what );
+    };
+}
+
+ +
+
+ + diff --git a/doc/reference.rst b/doc/reference.rst new file mode 100755 index 0000000..c520be7 --- /dev/null +++ b/doc/reference.rst @@ -0,0 +1,350 @@ +========= +Reference +========= + +The documentation is divided into a an explanation for +each container. All the common interface is explained only once, +but links are always provided to the relevant links. +Please make sure you understand +the `Clonable `_ concept and +the `Clone Allocator `_ concept. + +- `Conventions `_ +- `The Clonable concept`_ +- `The Clone Allocator concept`_ +- Class `reversible_ptr_container `_ +- Class `associative_ptr_container `_ +- `Pointer container adapters`_ + + - `ptr_sequence_adapter `_ + - `ptr_set_adapter `_ + - `ptr_multiset_adapter `_ + - `ptr_map_adapter `_ + - `ptr_multimap_adapter `_ +- `Sequence containers`_ + + - `ptr_vector `_ + - `ptr_deque `_ + - `ptr_list `_ + - `ptr_array `_ +- `Associative containers`_ + + - `ptr_set `_ + - `ptr_multiset `_ + - `ptr_map `_ + - `ptr_multimap `_ +- `Map iterator operations`_ +- `Indirected functions `_ +- `Class nullable`_ +- `Exception classes`_ + + + + +The Clonable concept +++++++++++++++++++++ + +**Refinement of** + +- Copy Constructible +- Heap Allocable +- Heap Deallocable + +The Clonable concept is introduced to formalize the requirements for +copying heap-allocated objects. A type ``T`` might be Clonable even though it +is not Assignable or Copy Constructible. Notice that many operations on +the containers does not even require the stored type to be Clonable. + +**Notation** + +======================= ============================================ =================== ===================== + **Type** **Object** (``const`` or non-``const``) **Pointer** **Describes** + ``T`` ``a`` ``ptr`` A Clonable type +======================= ============================================ =================== ===================== + +**Valid expressions** + +===================================== =========================== ======================================================================================== + **Expression** **Type** **Semantics** + ``new_clone(a);`` ``T*`` Allocate a new object that can be considered equivalent to the ``a`` object + ``delete_clone(ptr);`` ``void`` Deallocate an object previously allocated with ``allocate_clone()``. Must not throw +===================================== =========================== ======================================================================================== + + +Default implementation +---------------------- + +In the ```` header a default implementation +of the two functions is given: + +.. parsed-literal:: + + namespace boost + { + template< class T > + inline T* new_clone( const T& t ) + { + return new T( t ); + } + + template< class T > + void delete_clone( const T* t ) + { + checked_delete( r ); + } + } + + +Notice that this implementation makes normal Copy Constructible classes are automatically +Clonable unless ``operator new()`` or ``operator delete()`` are hidden. + +The two functions represent a layer of indirection which is necessary to support +classes that are not Copy Constructible by default. Notice that the implementation +relies on argument-dependent lookup (ADL) to find the right version of +``new_clone()`` and ``delete_clone()``. This means that one does not need to overload or specialize +the function is the boost namespace, but it can be placed together with +the rest of the interface of the class. If you are implementing a class +inline in headers, remember to forward declare the functions. + +The Clone Allocator concept ++++++++++++++++++++++++++++ + +The Clone Allocator concept is introduced to formalize the way +pointer containers controls memory of +the stored objects (and not the pointers to the stored objects). +The clone allocator allows +users to apply custom allocators/deallocators for the cloned objects. + +More information can be found below: + +.. contents:: :depth: 1 + :local: + + +Clone Allocator requirements +---------------------------- + +**Notation** + +===================== ============================================= ================================================== + **Type** **Object** (``const`` or non-``const``) **Describes** + ``T`` ``a`` A type + ``T*`` ``ptr`` A pointer to ``T`` +===================== ============================================= ================================================== + +**Valid expressions** + +====================================================== ============= ====================================================================================================================================================== + **Expression** **Type** **Semantics** + ``CloneAllocator::allocate_clone(a);`` ``T*`` Allocate a new object that can be considered equivalent to the ``a`` object + ``CloneAllocator::deallocate_clone(ptr);`` ``void`` Deallocate an object previously allocated with ``CloneAllocator::allocate_clone()`` or a compatible allocator. Must not throw. +====================================================== ============= ====================================================================================================================================================== + + + +The library comes with two predefined clone allocators. + +Class ``heap_clone_allocator`` +------------------------------ + +This is the default clone allocator used by all pointer containers. For most +purposes you will never have to change this default. + +**Definition** + +.. parsed-literal:: + + namespace boost + { + struct heap_clone_allocator + { + template< class U > + static U* allocate_clone( const U& r ) + { + return new_clone( r ); + } + + template< class U > + static void deallocate_clone( const U* r ) const + { + delete_clone( r ); + } + }; + } + +Notice that the above definition allows you to support custom allocation +schemes by relying on ``new_clone()`` and ``delete_clone()``. + +Class ``view_clone_allocator`` +------------------------------ + +This class provides a way to remove ownership properties of the +pointer containers. As its name implies, this means that you can +instead use the pointer containers as a view into an existing +container. + +**Definition** + +.. parsed-literal:: + + namespace boost + { + struct view_clone_allocator + { + template< class U > + static U* allocate_clone( const U& r ) + { + return const_cast(&r); + } + + template< class U > + static void deallocate_clone( const U* ) + { + // empty + } + }; + } + +**See also** + +- `Changing the clone allocator `_ + +Pointer container adapters +++++++++++++++++++++++++++ + +The pointer container adapters are used when you +want to make a pointer container starting from +your own "normal" container. For example, you +might have a map class that is extends ``std::map`` +in some way; the adapter class then allows you +to use your map class as a basis for a new +pointer container. + +The library provides an adapter for each type +of standard container: + +- ptr_sequence_adapter_ +- ptr_set_adapter_ +- ptr_multiset_adapter_ +- ptr_map_adapter_ +- ptr_multimap_adapter_ + +.. _ptr_sequence_adapter: ptr_sequence_adapter.html +.. _ptr_set_adapter: ptr_set_adapter.html +.. _ptr_multiset_adapter: ptr_multiset_adapter.html +.. _ptr_map_adapter: ptr_map_adapter.html +.. _ptr_multimap_adapter: ptr_multimap_adapter.html + + +Pointer containers +++++++++++++++++++ + +The pointer containers of this library are all built using +the `pointer container adapters`_. There is a pointer container +for each type of "normal" standard container: + +Sequence containers +------------------- + + - ptr_vector_ + - ptr_deque_ + - ptr_list_ + - ptr_array_ + +Associative containers +---------------------- + + - ptr_set_ + - ptr_multiset_ + - ptr_map_ + - ptr_multimap_ + +.. _ptr_vector: ptr_vector.html +.. _ptr_deque: ptr_deque.html +.. _ptr_list: ptr_list.html +.. _ptr_array: ptr_array.html +.. _ptr_set: ptr_set.html +.. _ptr_multiset: ptr_multiset.html +.. _ptr_map: ptr_map.html +.. _ptr_multimap: ptr_multimap.html + + +Map iterator operations ++++++++++++++++++++++++ + +The map iterators are a bit different compared to the normal ones. The +reason is that it is a bit clumsy to access the key and the mapped object +through i->first and i->second, and one tends to forget what is what. +Moreover, and more importantly, we also want to hide the pointer as much as possibble. +The new style can be illustrated with a small example:: + + typedef ptr_map map_t; + map_t m; + m[ "foo" ] = 4; // insert pair + m[ "bar" ] = 5; // ditto + ... + for( map_t::iterator i = m.begin(); i != m.end(); ++i ) + { + *i += 42; // add 42 to each value + cout << "value=" << *i << ", key=" << i.key() << "n"; + } + +So the difference from the normal map iterator is that + +- ``operator*()`` returns a reference to the mapped object (normally it returns a reference to a ``std::pair``, and +- that the key can be accessed through the ``key()`` function. + +Class ``nullable`` +++++++++++++++++++ + +The purpose of the class is simply to tell the containers +that null values should be allowed. Its definition is +trivial:: + + namespace boost + { + template< class T > + struct nullable + { + typedef T type; + }; + } + +Please notice that ``nullable`` has no effect on the containers +interface (except for ``is_null()`` functions). For example, it +does not make sense to do :: + + boost::ptr_vector< boost::nullable > vec; + vec.push_back( new boost::nullable ); // no no + boost::nullable& ref = vec[0]; // also no no + +Exception classes ++++++++++++++++++ + +There are three exceptions that are thrown by this library. The exception +hierarchy looks as follows:: + + + namespace boost + { + class bad_ptr_container_operation : public std::exception + { + public: + bad_ptr_container_operation( const char* what ); + }; + + class bad_index : public bad_ptr_container_operation + { + public: + bad_index( const char* what ); + }; + + class bad_pointer : public bad_ptr_container_operation + { + public: + bad_pointer(); + bad_pointer( const char* what ); + }; + } + +- `home `_ diff --git a/doc/reversible_ptr_container.html b/doc/reversible_ptr_container.html new file mode 100644 index 0000000..17bc3f7 --- /dev/null +++ b/doc/reversible_ptr_container.html @@ -0,0 +1,468 @@ + + + + + + + + + + +
+
+

Class reversible_ptr_container

+

This class is not a real class that can be found in the library. +Its purpose is to present the general interface of all the pointer containers.

+

Navigate:

+ +

synopsis:

+
+namespace boost
+{      
+    template
+    < 
+        class T, 
+        class CloneAllocator,
+        class VoidPtrContainer
+    >
+    class reversible_ptr_container 
+    {
+    public: // typedefs
+        typedef  T*                                           value_type;
+        typedef  T&                                           reference;
+        typedef  const T&                                     const_reference;
+        typedef  implementation defined                       iterator;
+        typedef  implementation defined                       const_iterator;
+        typedef  typename VoidPtrContainer::differnce_type    difference_type; 
+        typedef  typename VoidPtrContainer::size_type         size_type;
+        typedef  typename VoidPtrContainer::allocator_type    allocator_type;
+        typedef  implementation defined                       reverse_iterator;
+        typedef  implementation defined                       const_reverse_iterator;
+        typedef  typename VoidPtrContainer::iterator          ptr_iterator;
+        typedef  typename VoidPtrContainer::const_iterator    ptr_const_iterator;
+        typedef  implementation defined                       ptr_reverse_iterator;
+        typedef  implementation defined                       ptr_const_reverse_iterator;        
+        typedef  implementation defined                       auto_type;
+    
+    public: // construct/copy/destroy
+        reversible_ptr_container();
+        reversible_ptr_container( auto_ptr<reversible_ptr_container> r );
+        template< class InputIterator >
+        reversible_ptr_container( InputIterator first, InputIterator last );
+        ~reversible_ptr_container();
+        void operator=( std::auto_ptr<reversible_ptr_container> r )  
+        allocator_type get_allocator() const;                                      
+    
+    public: // iterators
+        iterator                begin();
+        const_iterator          begin() const;
+        iterator                end();
+        const_iterator          end() const;
+        reverse_iterator        rbegin();
+        const_reverse_iterator  rbegin() const;
+        reverse_iterator        rend();
+        const_reverse_iterator  rend() const;
+        
+        ptr_iterator                ptr_begin();
+        ptr_const_iterator          ptr_begin() const;
+        ptr_iterator                ptr_end();
+        ptr_const_iterator          ptr_end() const;
+        ptr_reverse_iterator        ptr_rbegin();
+        ptr_const_reverse_iterator  ptr_rbegin() const;
+        ptr_reverse_iterator        ptr_rend();
+        ptr_const_reverse_iterator  ptr_rend() const;
+
+    
+    public: // capacity
+        size_type  size() const;
+        size_type  max_size() const;
+        bool       empty() const;       
+    
+    public: // modifiers
+        void      swap( reversible_ptr_container& r );
+        void      clear():
+    
+    public: // pointer container requirements
+    
+        auto_type                                replace( iterator position, T* x );    
+        std::auto_ptr<reversible_ptr_container>  clone() const;    
+        std::auto_ptr<reversible_ptr_container>  release();
+        auto_type                                release( iterator position );
+    
+    }; //  class 'reversible_ptr_container'
+
+    // comparison            
+    template < class T, class CA, class VPC >
+    bool operator==( const reversible_ptr_container<T,CA,VPC>& x,
+                     const reversible_ptr_container<T,CA,VPC>& y);
+    
+    template < class T, class CA, class VPC  >
+    bool operator<( const reversible_ptr_container<T,CA,VPC>& x,
+                    const reversible_ptr_container<T,CA,VPC>& y);
+    
+    template < class T, class CA, class VPC  >
+    bool operator!=( const reversible_ptr_container<T,CA,VPC>& x,
+                     const reversible_ptr_container<T,CA,VPC>& y);
+    
+    template < class T,  class CA, class VPC >
+    bool operator>( const reversible_ptr_container<T,CA,VPC>& x,
+                    const reversible_ptr_container<T,CA,VPC>& y);
+    
+    template < class T,  class CA, class VPC >
+    bool operator>=( const reversible_ptr_container<T,CA,VPC>& x,
+                     const reversible_ptr_container<T,CA,VPC>& y);
+    
+    template < class T,  class CA, class VPC >
+    bool operator<=( const reversible_ptr_container<T,CA,VPC>& x,
+                     const reversible_ptr_container<T,CA,VPC>& y);
+    
+    template< class T,  class CA, class VPC  >
+    void swap( reversible_ptr_container<T,CA,VPC>& x, 
+               reversible_ptr_container<T,CA,VPC>& y );
+
+    // clonability
+    template< class T,  class CA, class VPC >
+    reversible_ptr_container<T,CA,VPC>* 
+    new_clone( const reversible_ptr_container<T,CA,VPC>& r );
+
+    // null predicate
+    template< class Iterator >
+    bool is_null( Iterator i );
+
+} // namespace 'boost'  
+
+
+
+

Semantics

+
+

Semantics: typedefs

+

Notice how these two types differ:

+
    +
  • typedef T* value_type;

    +
    +
      +
    • notice this has pointer type
    • +
    +
    +
  • +
  • typedef T& reference;

    +
    +
      +
    • notice this is not a pointer type
    • +
    +
    +
  • +
+

This is done to be able to add pointers directly +to the container, but to hide the pointers externally.

+ +

Also notice that

+
    +
  • typedef ... iterator
  • +
  • typedef ... ptr_iterator
  • +
+

allows one to iterate over T and void* objects, +respectively.

+
    +
  • typedef ... auto_type
  • +
+

This declaration hides a pointer pointer type. You can rely on the following +operations:

+
+T* operator->() const;
+T& operator*() const;
+T* release();
+~auto_type();    
+
+

The destructor will delete the stored object. It might help to +think it is just an std::auto_ptr<T>.

+
+
+

Semantics: construct/copy/destroy

+
    +
  • reversible_ptr_container();

    +
    +
      +
    • Effects: Constructs an empty container
    • +
    • Postconditions: size() == 0
    • +
    +
    +
  • +
+ +
    +
  • explicit reversible_ptr_container( std::auto_ptr< reversible_ptr_container > r );

    +
    +
      +
    • Effects: Constructs a container by taking ownership of the supplied pointers
    • +
    +
    +
  • +
  • template< class InputIterator > +reversible_ptr_container( InputIterator first, InputIterator last );

    +
    +
      +
    • Requirements: (first,last] is a valid range
    • +
    • Effects: Constructs a container with a cloned range of (first,last]
    • +
    • Postconditions: size() == std::distance( first, last )
    • +
    +
    +
  • +
  • ~reversible_ptr_container();

    +
    +
      +
    • Effects: Deletes the stored objects
    • +
    • Throws: Nothing
    • +
    +
    +
  • +
  • void operator=( std::auto_ptr<reversible_ptr_container> r );

    +
    +
      +
    • Effects: Deletes the stored objects and then takes ownership of the supplied pointers
    • +
    • Throws: Nothing
    • +
    +
    +
  • +
  • allocator_type get_allocator() const;

    +
    +
      +
    • Effects: Returns a copy of the allocator of the container object
    • +
    +
    +
  • +
+
+
+

Semantics: iterators

+
    +
  • iterator begin();

    +
  • +
  • const_iterator begin() const;

    +
    +
      +
    • Effects: Returns a mutable/non-mutable iterator with value_type T
    • +
    • Throws: Nothing
    • +
    +
    +
  • +
  • iterator end();

    +
  • +
  • const_iterator end() const;

    +
    +
      +
    • Effects: Returns a mutable/non-mutable iterator with value_type T
    • +
    • Throws: Nothing
    • +
    +
    +
  • +
  • reverse_iterator rbegin();

    +
  • +
  • const_reverse_iterator rbegin() const;

    +
    +
      +
    • Effects: Returns a mutable/non-mutable reverse iterator with value_type T
    • +
    • Throws: Nothing
    • +
    +
    +
  • +
  • reverse_iterator rend();

    +
  • +
  • const_reverse_iterator rend() const;

    +
    +
      +
    • Effects: Returns a mutable/non-mutable reverse iterator with value_type T
    • +
    • Throws: Nothing
    • +
    +
    +
  • +
  • ptr_iterator ptr_begin();

    +
  • +
  • ptr_const_iterator ptr_begin() const;

    +
    +
      +
    • Effects: Returns a mutable/non-mutable iterator with value_type void*
    • +
    • Throws: Nothing
    • +
    +
    +
  • +
  • ptr_iterator ptr_end();

    +
  • +
  • ptr_const_iterator ptr_end() const;

    +
    +
      +
    • Effects: Returns a mutable/non-mutable iterator with value_type void*
    • +
    • Throws: Nothing
    • +
    +
    +
  • +
  • ptr_reverse_iterator ptr_rbegin();

    +
  • +
  • ptr_const_reverse_iterator ptr_rbegin() const;

    +
    +
      +
    • Effects: Returns a mutable/non-mutable reverse iterator with value_type void*
    • +
    • Throws: Nothing
    • +
    +
    +
  • +
  • ptr_reverse_iterator ptr_rend();

    +
  • +
  • ptr_const_reverse_iterator ptr_rend() const;

    +
    +
      +
    • Effects: Returns a mutable/non-mutable iterator with value_type void*
    • +
    • Throws: Nothing
    • +
    +
    +
  • +
+
+
+

Semantics: capacity

+
    +
  • size_type size() const;

    +
    +
      +
    • Effects: Returns the number of stored elements
    • +
    • Throws: Nothing
    • +
    +
    +
  • +
  • size_type max_size() const;

    +
    +
      +
    • Effects: Returns the maximum number of stored elements
    • +
    • Throws: Nothing
    • +
    +
    +
  • +
  • bool empty() const;

    +
    +
      +
    • Effects: Returns whether the container is empty or not
    • +
    • Throws: Nothing
    • +
    +
    +
  • +
+
+
+

Semantics: modifiers

+
    +
  • void swap( reversible_ptr_container& r );

    +
    +
      +
    • Effects: Swaps the content of the two containers
    • +
    • Throws: Nothing
    • +
    +
    +
  • +
  • void clear();

    +
    +
      +
    • Effects: Destroys all object of the container
    • +
    • Postconditions: empty() == true
    • +
    • Throws: Nothing
    • +
    +
    +
  • +
+
+
+

Semantics: pointer container requirements

+
    +
  • auto_type replace( iterator position, T* x );

    +
    +
      +
    • Requirements: not empty() and x != 0
    • +
    • Effects: returns the object pointed to by position and replaces it with x.
    • +
    • Throws: bad_ptr_container_operation if the container is empty and bad_pointer if x == 0.
    • +
    • Exception safety: Strong guarantee
    • +
    +
    +
  • +
  • std::auto_ptr< reversible_ptr_container > clone() const;

    +
    +
      +
    • Effects: Returns a deep copy of the container
    • +
    • Throws: std::bad_alloc if there is not enough memory to make a clone of the container
    • +
    • Complexity: Linear
    • +
    +
    +
  • +
  • std::auto_ptr< reversible_ptr_container > release();

    +
    +
      +
    • Effects: Releases ownership of the container. This is a useful way of returning a container from a function.
    • +
    • Postconditions: empty() == true
    • +
    • Throws: std::bad_alloc if the return value cannot be allocated
    • +
    • Exception safety: Strong guarantee
    • +
    +
    +
  • +
  • auto_type release( iterator position );

    +
    +
      +
    • Requirements: not empty();
    • +
    • Effects: Releases ownership of the pointer referred to by position
    • +
    • Postconditions: size() is one less
    • +
    • Throws: bad_ptr_container_operation if the container is empty
    • +
    • Exception safety: Strong guarantee
    • +
    +
    +
  • +
+
+
+

Semantics: comparison

+

These functions compare the underlying range of objects. +So

+
+operation( const ptr_container& l, const ptr_container& r );
+
+

has the effect one would expect of normal standard containers. Hence +objects are compared and not the pointers to objects.

+
+
+

Semantics: clonability

+
    +
  • template< class T, class CloneAllocator > +reversible_ptr_container<T,CA,VPC>* +new_clone( const reversible_ptr_container<T,CA,VPC>& r );

    +
    + +
    +
  • +
+
+
+

Semantics: null predicate

+
    +
  • template< class Iterator > bool is_null( Iterator i );

    +
    +
      +
    • Requirements: i is a valid dereferencable iterator
    • +
    • Returns: *i.base() == 0;
    • +
    +
    +
  • +
+
+
+
+ + diff --git a/doc/reversible_ptr_container.rst b/doc/reversible_ptr_container.rst new file mode 100755 index 0000000..1ae9bc6 --- /dev/null +++ b/doc/reversible_ptr_container.rst @@ -0,0 +1,431 @@ + +Class ``reversible_ptr_container`` +------------------------------------ + +This class is not a real class that can be found in the library. +Its purpose is to present the general interface of all the pointer containers. + +**Navigate:** + +- `home `_ +- `reference `_ + +**synopsis:** + +.. parsed-literal:: + + namespace boost + { + template + < + class T, + class CloneAllocator, + class VoidPtrContainer + > + class reversible_ptr_container + { + public: // `typedefs`_ + typedef T* value_type; + typedef T& reference; + typedef const T& const_reference; + typedef *implementation defined* iterator; + typedef *implementation defined* const_iterator; + typedef typename VoidPtrContainer::differnce_type difference_type; + typedef typename VoidPtrContainer::size_type size_type; + typedef typename VoidPtrContainer::allocator_type allocator_type; + typedef *implementation defined* reverse_iterator; + typedef *implementation defined* const_reverse_iterator; + typedef typename VoidPtrContainer::iterator ptr_iterator; + typedef typename VoidPtrContainer::const_iterator ptr_const_iterator; + typedef *implementation defined* ptr_reverse_iterator; + typedef *implementation defined* ptr_const_reverse_iterator; + typedef *implementation defined* auto_type; + + public: // `construct/copy/destroy`_ + reversible_ptr_container(); + reversible_ptr_container( auto_ptr r ); + template< class InputIterator > + reversible_ptr_container( InputIterator first, InputIterator last ); + ~reversible_ptr_container(); + void operator=( std::auto_ptr r ) + allocator_type get_allocator() const; + + public: // `iterators`_ + iterator begin(); + const_iterator begin() const; + iterator end(); + const_iterator end() const; + reverse_iterator rbegin(); + const_reverse_iterator rbegin() const; + reverse_iterator rend(); + const_reverse_iterator rend() const; + + ptr_iterator ptr_begin(); + ptr_const_iterator ptr_begin() const; + ptr_iterator ptr_end(); + ptr_const_iterator ptr_end() const; + ptr_reverse_iterator ptr_rbegin(); + ptr_const_reverse_iterator ptr_rbegin() const; + ptr_reverse_iterator ptr_rend(); + ptr_const_reverse_iterator ptr_rend() const; + + + public: // `capacity`_ + size_type size() const; + size_type max_size() const; + bool empty() const; + + public: // `modifiers`_ + void swap( reversible_ptr_container& r ); + void clear(): + + public: // `pointer container requirements`_ + + auto_type replace( iterator position, T* x ); + std::auto_ptr clone() const; + std::auto_ptr release(); + auto_type release( iterator position ); + + }; // class 'reversible_ptr_container' + + // `comparison`_ + template < class T, class CA, class VPC > + bool operator==( const reversible_ptr_container& x, + const reversible_ptr_container& y); + + template < class T, class CA, class VPC > + bool operator<( const reversible_ptr_container& x, + const reversible_ptr_container& y); + + template < class T, class CA, class VPC > + bool operator!=( const reversible_ptr_container& x, + const reversible_ptr_container& y); + + template < class T, class CA, class VPC > + bool operator>( const reversible_ptr_container& x, + const reversible_ptr_container& y); + + template < class T, class CA, class VPC > + bool operator>=( const reversible_ptr_container& x, + const reversible_ptr_container& y); + + template < class T, class CA, class VPC > + bool operator<=( const reversible_ptr_container& x, + const reversible_ptr_container& y); + + template< class T, class CA, class VPC > + void swap( reversible_ptr_container& x, + reversible_ptr_container& y ); + + // clonability_ + template< class T, class CA, class VPC > + reversible_ptr_container* + new_clone( const reversible_ptr_container& r ); + + // `null predicate`_ + template< class Iterator > + bool is_null( Iterator i ); + + } // namespace 'boost' + + + +Semantics +--------- + +.. _`typedefs`: + +Semantics: typedefs +^^^^^^^^^^^^^^^^^^^ + +Notice how these two types differ: + + +- ``typedef T* value_type;`` + + - notice this has pointer type + +- ``typedef T& reference;`` + + - notice this is not a pointer type + +This is done to be able to add pointers directly +to the container, but to hide the pointers externally. + +.. + - ``typedef *implementation defined* object_type;`` + - this is ``T`` for sequences and sets + - this is ``std::pair`` for maps + +Also notice that + +- ``typedef ... iterator`` + +- ``typedef ... ptr_iterator`` + +allows one to iterate over ``T`` and ``void*`` objects, +respectively. + +- ``typedef ... auto_type`` + +This declaration hides a pointer pointer type. You can rely on the following +operations:: + + T* operator->() const; + T& operator*() const; + T* release(); + ~auto_type(); + +The destructor will delete the stored object. It might help to +think it is just an ``std::auto_ptr``. + +.. _construct/copy/destroy: + +Semantics: construct/copy/destroy +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- ``reversible_ptr_container();`` + + - Effects: Constructs an empty container + + - Postconditions: ``size() == 0`` + +.. + - ``reversible_ptr_container( size_type n, const T& x );`` + + - Effects: Constructs a container with ``n`` clones of ``x`` + + - Postconditions: ``size() == n`` + +- ``explicit reversible_ptr_container( std::auto_ptr< reversible_ptr_container > r );`` + + - Effects: Constructs a container by taking ownership of the supplied pointers + + +- ``template< class InputIterator >`` + ``reversible_ptr_container( InputIterator first, InputIterator last );`` + + - Requirements: ``(first,last]`` is a valid range + + - Effects: Constructs a container with a cloned range of ``(first,last]`` + + - Postconditions: ``size() == std::distance( first, last )`` + +- ``~reversible_ptr_container();`` + + - Effects: Deletes the stored objects + + - Throws: Nothing + +- ``void operator=( std::auto_ptr r );`` + + - Effects: Deletes the stored objects and then takes ownership of the supplied pointers + + - Throws: Nothing + +- ``allocator_type get_allocator() const;`` + + - Effects: Returns a copy of the allocator of the container object + + +.. _iterators: + +Semantics: iterators +^^^^^^^^^^^^^^^^^^^^ + +- ``iterator begin();`` +- ``const_iterator begin() const;`` + + - Effects: Returns a mutable/non-mutable iterator with ``value_type T`` + + - Throws: Nothing + +- ``iterator end();`` +- ``const_iterator end() const;`` + + - Effects: Returns a mutable/non-mutable iterator with ``value_type T`` + + - Throws: Nothing + +- ``reverse_iterator rbegin();`` + +- ``const_reverse_iterator rbegin() const;`` + + - Effects: Returns a mutable/non-mutable reverse iterator with ``value_type T`` + + - Throws: Nothing + +- ``reverse_iterator rend();`` + +- ``const_reverse_iterator rend() const;`` + + - Effects: Returns a mutable/non-mutable reverse iterator with ``value_type T`` + + - Throws: Nothing + +- ``ptr_iterator ptr_begin();`` + +- ``ptr_const_iterator ptr_begin() const;`` + + - Effects: Returns a mutable/non-mutable iterator with ``value_type void*`` + + - Throws: Nothing + +- ``ptr_iterator ptr_end();`` + +- ``ptr_const_iterator ptr_end() const;`` + + - Effects: Returns a mutable/non-mutable iterator with ``value_type void*`` + + - Throws: Nothing + +- ``ptr_reverse_iterator ptr_rbegin();`` + +- ``ptr_const_reverse_iterator ptr_rbegin() const;`` + + - Effects: Returns a mutable/non-mutable reverse iterator with ``value_type void*`` + + - Throws: Nothing + +- ``ptr_reverse_iterator ptr_rend();`` + +- ``ptr_const_reverse_iterator ptr_rend() const;`` + + - Effects: Returns a mutable/non-mutable iterator with ``value_type void*`` + + - Throws: Nothing + + +.. _capacity: + +Semantics: capacity +^^^^^^^^^^^^^^^^^^^ + +- ``size_type size() const;`` + + - Effects: Returns the number of stored elements + + - Throws: Nothing + +- ``size_type max_size() const;`` + + - Effects: Returns the maximum number of stored elements + + - Throws: Nothing + +- ``bool empty() const;`` + + - Effects: Returns whether the container is empty or not + + - Throws: Nothing + + +.. _modifiers: + +Semantics: modifiers +^^^^^^^^^^^^^^^^^^^^ + +- ``void swap( reversible_ptr_container& r );`` + + - Effects: Swaps the content of the two containers + + - Throws: Nothing + +- ``void clear();`` + + - Effects: Destroys all object of the container + + - Postconditions: ``empty() == true`` + + - Throws: Nothing + + +.. _`pointer container requirements`: + +Semantics: pointer container requirements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- ``auto_type replace( iterator position, T* x );`` + + - Requirements: ``not empty() and x != 0`` + + - Effects: returns the object pointed to by ``position`` and replaces it with ``x``. + + - Throws: ``bad_ptr_container_operation`` if the container is empty and ``bad_pointer`` if ``x == 0``. + + - Exception safety: Strong guarantee + +- ``std::auto_ptr< reversible_ptr_container > clone() const;`` + + - Effects: Returns a deep copy of the container + + - Throws: ``std::bad_alloc`` if there is not enough memory to make a clone of the container + + - Complexity: Linear + +- ``std::auto_ptr< reversible_ptr_container > release();`` + + - Effects: Releases ownership of the container. This is a useful way of returning a container from a function. + + - Postconditions: ``empty() == true`` + + - Throws: ``std::bad_alloc`` if the return value cannot be allocated + + - Exception safety: Strong guarantee + +- ``auto_type release( iterator position );`` + + - Requirements: ``not empty();`` + + - Effects: Releases ownership of the pointer referred to by position + + - Postconditions: ``size()`` is one less + + - Throws: ``bad_ptr_container_operation`` if the container is empty + + - Exception safety: Strong guarantee + + +.. _comparison: + +Semantics: comparison +^^^^^^^^^^^^^^^^^^^^^ + +These functions compare the underlying range of objects. +So :: + + operation( const ptr_container& l, const ptr_container& r ); + +has the effect one would expect of normal standard containers. Hence +objects are compared and not the pointers to objects. + +.. _`clonability`: + +Semantics: clonability +^^^^^^^^^^^^^^^^^^^^^^ + +- ``template< class T, class CloneAllocator > + reversible_ptr_container* + new_clone( const reversible_ptr_container& r );`` + + + - Effects: ``return r.clone().release();`` + + - Remarks: This function is only defined for concrete `pointer containers`_, but not for + `pointer container adapters`_. + +.. _`pointer containers`: ptr_container.html#smart-containers +.. _`pointer container adapters`: ptr_container.html#smart-container-adapters + +.. _`null predicate`: + +Semantics: null predicate +^^^^^^^^^^^^^^^^^^^^^^^^^ + +- ``template< class Iterator > bool is_null( Iterator i );`` + + - Requirements: ``i`` is a valid dereferencable iterator + + - Returns: ``*i.base() == 0;`` + + diff --git a/doc/todo.txt b/doc/todo.txt new file mode 100755 index 0000000..d3d4aea --- /dev/null +++ b/doc/todo.txt @@ -0,0 +1,71 @@ +Hi, + +3. improve docs as discussed during the review + +5. add more debug checks after access to ptr_begin(), ptr_end() + +7. improve tests + +8. test for replace and 0. All functions that can take a null + might need to handle it?? + +------------------- + +10) Specify difference between assignment from an input_iterator (basic exception safety guarantee) + and any other iterator (strong exception safety guarantee). Provide a iterator wrapper + which implement the input_iterator concept to achieve that particular performance characteristic: + vector.assign( fast_copy_iterator( other.begin() ), other.end() ); + +20) Add two sources and a discussion on defaults: http://www.gotw.ca/gotw/054.htm, http://www.codeproject.com/vcpp/stl/vector_vs_deque.asp + +45) update all functions with correct exception specs + +46) add description to erase() which returns end in some circumstances + +47) Consider if list implemetation of multi-insert can benefit + from strong exception-safety. + +48) should the clone_allocator be changed to + + struct shared_ptr_allocator + { + typedef shared_ptr ptr_type; + + ptr_type allocate_clone( const T& r ) + { + return ptr_type( new_clone(r) ); + } + + void deallocate_clone( const ptr_type& ) + { } + + template< class Iter > + ptr_type get_ptr_from_iterator( Iter i ) + { + // default reurn &*i; + return *i; + } + }; + + shared_ptr new_clone( const Foo& r ) + { ... }; // bad for generality + +74) consider simple static assert by nesting a typedef a la +T::boost_indirect_container + +75) toturial: + +ptr_map: + +add default constructor + +map[ "foo" ].set_data( "Bla bla", 6 ); + +boost.assign -support: + +ptr_insert( ptr_map )( "foo", "bla bla", 3 ) + ( "bar", "foo", 3 ); + + + + diff --git a/doc/tut1.html b/doc/tut1.html new file mode 100755 index 0000000..069ad8f --- /dev/null +++ b/doc/tut1.html @@ -0,0 +1,357 @@ + + + + + + + + + + +
+//
+// This example is intended to get you started.
+// Notice how the smart container
+//
+// 1. takes ownership of objects
+// 2. transfers ownership
+// 3. applies indirection to iterators 
+// 4. clones objects from other smart containers
+// 
+
+//
+// First we select which container to use.
+//
+#include <boost/smart_container/ptr_deque.hpp>
+
+//
+// we need these later in the example
+//
+#include <boost/assert.hpp>
+#include <string>
+#include <exception>
+
+
+//
+// Then we define a small polymorphic class
+// hierarchy.
+// 
+
+class animal
+{
+    virtual std::string do_speak() const = 0;
+    std::string name_;
+
+protected:
+    //
+    // Animals cannot be copied...
+    //
+    animal( const animal& r ) : name_( r.name_ )           { }
+    void operator=( const animal& );
+
+private:
+    //
+    // ...but due to advances in genetics, we can clone them!
+    //
+
+    virtual animal* do_clone() const = 0;
+        
+public:
+    animal( const std::string& name ) : name_(name)        { }
+    virtual ~animal() throw()                              { }
+    
+    std::string speak() const
+    {
+        return do_speak();
+    }
+
+    std::string name() const
+    {
+        return name_;
+    }
+
+    animal* clone() const
+    {
+        return do_clone();
+    }
+};
+
+//
+// An animal is still not Clonable. We need this last hook.
+//
+// Notice that we pass the animal by const reference
+// and return by pointer.
+//
+
+animal* allocate_clone( const animal& a )
+{
+    return a.clone();
+}
+
+//
+// We do not need to define 'delete_clone()' since
+// since the default is to call the default 'operator delete()'.
+//
+
+const std::string muuuh = "Muuuh!";
+const std::string oiink = "Oiiink";
+
+class cow : public animal
+{
+    virtual std::string do_speak() const
+    {
+        return muuuh;
+    }
+
+    virtual animal* do_clone() const
+    {
+        return new cow( *this );
+    }
+
+public:
+    cow( const std::string& name ) : animal(name)          { }
+};
+
+class pig : public animal
+{
+    virtual std::string do_speak() const
+    {
+        return oiink;
+    }
+
+    virtual animal* do_clone() const
+    {
+        return new pig( *this );
+    }
+    
+public:
+    pig( const std::string& name ) : animal(name)          { }
+};
+
+//
+// Then we, of course, need a place to put all
+// those animals.
+//
+
+class farm
+{
+    //
+    // This is where the smart containers are handy
+    //
+    typedef boost::ptr_deque<animal> barn_type;
+    barn_type                      barn;
+
+    //
+    // An error type
+    //
+    struct farm_trouble : public std::exception           { };
+
+public:
+    // 
+    // We would like to make it possible to
+    // iterate over the animals in the farm
+    //
+    typedef barn_type::iterator  animal_iterator;
+
+    //
+    // We also need to count the farm's size...
+    //
+    typedef barn_type::size_type size_type;
+    
+    //
+    // And we also want to transfer an animal
+    // safely around. The easiest way to think
+    // about '::auto_type' is to imagine a simplified
+    // 'std::auto_ptr<T>' ... this means you can expect
+    // 
+    //   T* operator->()
+    //   T* release()
+    //   deleting destructor
+    //
+    // but not more.
+    //
+    typedef barn_type::auto_type  animal_transport;
+
+    // 
+    // Create an empty farm.
+    //
+    farm()                                                 { }
+    
+    //
+    // We need a constructor that can make a new
+    // farm by cloning a range of animals.
+    //
+    farm( animal_iterator begin, animal_iterator end )
+     : 
+        //
+        // Objects are always cloned before insertion
+        // unless we explicitly add a pointer or 
+        // use 'release()'. Therefore we actually
+        // clone all animals in the range
+        //
+        barn( begin, end )                               { }
+    
+    //
+    // ... so we need some other function too
+    //
+
+    animal_iterator begin()
+    {
+        return barn.begin();
+    }
+
+    animal_iterator end()
+    {
+        return barn.end();
+    }
+    
+    //
+    // Here it is quite ok to have an 'animal*' argument.
+    // The smart container will handle all ownership
+    // issues.
+    //
+    void buy_animal( animal* a )
+    {
+        barn.push_back( a );
+    }
+
+    //
+    // The farm can also be in economical trouble and
+    // therefore be in the need to sell animals.
+    //
+    animal_transport sell_animal( animal_iterator to_sell )
+    {
+        if( to_sell == end() )
+            throw farm_trouble();
+
+        //
+        // Here we remove the animal from the barn,
+        // but the animal is not deleted yet...it's
+        // up to the buyer to decide what
+        // to do with it.
+        //
+        return barn.release( to_sell );
+    }
+
+    //
+    // How big a farm do we have?
+    //
+    size_type size() const
+    {
+        return barn.size();
+    }
+
+    //
+    // If things are bad, we might choose to sell all animals :-(
+    //
+    std::auto_ptr<barn_type> sell_farm()
+    {
+        return barn.release();
+    }
+
+    //
+    // However, if things are good, we might buy somebody
+    // else's farm :-)
+    //
+
+    void buy_farm( std::auto_ptr<barn_type> other )
+    {
+        //
+        // This line inserts all the animals from 'other'
+        // and is guaranteed either to succeed or to have no
+        // effect
+        //
+        barn.transfer( barn.end(), // insert new animals at the end
+                         *other );     // we want to transfer all animals,
+                                       // so we use the whole container as argument
+        //
+        // You might think you would have to do
+        //
+        // other.release();
+        //
+        // but '*other' is empty and can go out of scope as it wants
+        //
+        BOOST_ASSERT( other->empty() );
+    }
+    
+}; // class 'farm'.
+
+int main()
+{
+    //
+    // First we make a farm
+    //
+    farm animal_farm;
+    BOOST_ASSERT( animal_farm.size() == 0u );
+    
+    animal_farm.buy_animal( new pig("Betty") );
+    animal_farm.buy_animal( new pig("Benny") );
+    animal_farm.buy_animal( new pig("Jeltzin") );
+    animal_farm.buy_animal( new cow("Hanz") );
+    animal_farm.buy_animal( new cow("Mary") );
+    animal_farm.buy_animal( new cow("Frederik") );
+    BOOST_ASSERT( animal_farm.size() == 6u );
+
+    //
+    // Then we make another farm...it will actually contain
+    // a clone of the other farm.
+    //
+    farm new_farm( animal_farm.begin(), animal_farm.end() );
+    BOOST_ASSERT( new_farm.size() == 6u );
+
+    //
+    // Is it really clones in the new farm?
+    //
+    BOOST_ASSERT( new_farm.begin()->name() == "Betty" );
+    
+    //
+    // Then we search for an animal, Mary (the Crown Princess of Denmark),
+    // because we would like to buy her ...
+    //
+    typedef farm::animal_iterator iterator;
+    iterator to_sell;
+    for( iterator i   = animal_farm.begin(),
+                  end = animal_farm.end();
+         i != end; ++i )
+    {
+        if( i->name() == "Mary" )
+        {
+            to_sell = i;
+            break;
+        }
+    }
+
+    farm::animal_transport mary = animal_farm.sell_animal( to_sell );
+
+
+    if( mary->speak() == muuuh )
+        //
+        // Great, Mary is a cow, and she may live longer
+        //
+        new_farm.buy_animal( mary.release() );
+    else
+        //
+        // Then the animal would be destroyed (!)
+        // when we go out of scope.
+        //
+        ;
+
+    //
+    // Now we can observe some changes to the two farms...
+    //
+    BOOST_ASSERT( animal_farm.size() == 5u );
+    BOOST_ASSERT( new_farm.size()    == 7u );
+
+    //
+    // The new farm has however underestimated how much
+    // it cost to feed Mary and its owner is forced to sell the farm...
+    //
+    animal_farm.buy_farm( new_farm.sell_farm() );
+
+    BOOST_ASSERT( new_farm.size()    == 0u );
+    BOOST_ASSERT( animal_farm.size() == 12u );     
+}
+
+ + + diff --git a/doc/tut2.html b/doc/tut2.html new file mode 100755 index 0000000..f39cb4d --- /dev/null +++ b/doc/tut2.html @@ -0,0 +1,176 @@ + + + + + + + + + + +
+//
+// This example is intended to show you how to
+// use the 'view_clone_manager'. The idea
+// is that we have a container of non-polymorphic
+// objects and want to keep then sorted by different
+// criteria at the same time. 
+//
+
+//
+// We'll go for 'ptr_vector' here. Using a node-based 
+// container would be a waste of space here.
+// All container headers will also include
+// the Clone Managers.
+// 
+#include <boost/smart_container/ptr_vector.hpp>
+#include <boost/smart_container/ptr_predicate.hpp>
+
+#include <cstdlib>   // For 'rand()'
+#include <algorithm> // For 'std::sort()'
+#include <iostream>  // For 'std::cout'
+
+
+//
+// This is our simple example data-structure. It can
+// be ordered in three ways.
+//
+struct photon
+{
+    photon() : color( std::rand() ), 
+               direction( std::rand() ),
+               power( std::rand() )
+    { }
+    
+    int color;
+    int direction;
+    int power;
+};
+
+//
+// Our big container is a standard vector
+//
+typedef std::vector<photon>                                 vector_type;
+
+//
+// Now we define our view type by adding a second template argument.
+// The 'view_clone_manager' will implements Cloning by taking address
+// of objects.
+//
+// Notice the first template argument is 'photon' and not
+// 'const photon' to allow the view container write access.
+//
+typedef boost::ptr_vector<photon,boost::view_clone_manager> view_type;
+
+//
+// Our first sort criterium
+//
+struct sort_by_color
+{
+    bool operator()( const photon& l, const photon& r ) const
+    {
+        return l.color < r.color;
+    }
+};
+
+//
+// Our second sort criterium
+//
+struct sort_by_direction
+{
+    bool operator()( const photon& l, const photon& r ) const
+    {
+        return l.direction < r.direction;
+    }
+};
+
+
+//
+// Our third sort criterium
+//
+struct sort_by_power
+{
+    bool operator()( const photon& l, const photon& r ) const
+    {
+        return l.power < r.power;
+    }
+};
+
+//
+// This function inserts "Clones" into the
+// the view. 
+//
+// We need to pass the first argument
+// as a non-const reference to be able to store
+// 'T*' instead of 'const T*' objects. Alternatively,
+// we might change the declaration of the 'view_type'
+// to 
+//     typedef boost::ptr_vector<const photon,boost::view_clone_manager> 
+//               view_type;     ^^^^^^
+//
+void insert( vector_type& from, view_type& to )
+{
+        to.insert( to.end(), 
+                   from.begin(),
+                   from.end() );
+}
+
+int main()
+{
+    enum { sz = 10, count = 500 };
+
+    //
+    // First we create the main container and two views
+    //
+    std::vector<vector_type>  photons;
+    view_type                 color_view;
+    view_type                 direction_view;
+
+    //
+    // Then we fill the main container with some random data
+    //
+    for( int i = 0; i != sz; ++i )
+    {
+        photons.push_back( vector_type() ); 
+
+        for( int j = 0; j != count; ++j )
+            photons[i].push_back( photon() );
+    }
+
+    //
+    // Then we create the two views.
+    //
+    for( int i = 0; i != sz; ++i )
+    {
+        insert( photons[i], color_view );
+        insert( photons[i], direction_view );
+    }
+
+    //
+    // First we sort the original photons, using one of
+    // the view classes. This may sound trivial, but consider that
+    // the objects are scatered all around 'sz' different vectors;
+    // the view makes them act as one big vector.
+    //
+    // Notice how we simple use
+    // '.begin()/end()' instead of '.ptr_begin()/ptr_end()':
+    //
+    std::sort( color_view.begin(), color_view.end(), sort_by_power() );
+    
+    //
+    // And now we can sort the views themselves. Notice how
+    // we switch to different iterators and different predicates:
+    //
+    std::sort( color_view.ptr_begin(), color_view.ptr_end(),
+               boost::indirected2<sort_by_color>() );
+
+    std::sort( direction_view.ptr_begin(), direction_view.ptr_end(),
+               boost::indirected2<sort_by_direction>() );
+
+    return 0;
+}
+
+
+ + + diff --git a/doc/tutorial.html b/doc/tutorial.html new file mode 100644 index 0000000..f38c4e5 --- /dev/null +++ b/doc/tutorial.html @@ -0,0 +1,332 @@ + + + + + + +Tutorial + + + +
+

Tutorial

+

The tutorial shows you the most simple usage of the +library. It is assumed that the reader is familiar +with the use of standard containers. Although +the tutorial is devided into sections, it is recommended +that you read it all from top to bottom.

+ +
+

Basic usage

+

The most important aspect of a pointer container is that it manages +memory for you. This means that you in most cases do not need to worry +about deleting memory.

+

Let us assume that we have an OO-hierarchy of animals

+
+class animal : boost::noncopyable
+{
+public:
+    virtual ~animal() {}
+    void     eat();
+    // ...
+};
+
+class mammal : public animal
+{
+    // ...
+};
+
+class bird : public animal
+{
+    // ...
+};
+
+

Then the managing of the animals is straight-forward. Imagine a +Zoo:

+
+class zoo
+{
+    boost::ptr_vector<animal> the_animals;
+public:
+
+    void add_animal( animal* a )
+    {
+        the_animals.push_back( a );
+    }
+};
+
+

Notice how just pass the class name to the container; there +is no * to indicate it is a pointer. +With this declaration we can now say:

+
+zoo the_zoo;
+the_zoo.add_animal( new mammal("joe") );
+the_zoo.add_animal( new bird("dodo") );
+
+

Thus we heap-allocate all elements of the container +and never rely on copy-semantics.

+
+
+

Indirected interface

+

As particular feature of the pointer containers is that +the query interface is indirected. For example,

+
+boost::ptr_vector<animal> vec;
+vec.push_back( new animal ); // you add it as pointer ...
+vec[0].eat();                // but get a reference back
+
+

This indirection also happens to iterators, so

+
+typedef std::vector<animal*> std_vec;
+std_vec vec;
+...
+std_vec::iterator i = vec.begin();
+(*i)->eat(); // '*' needed
+
+

now becomes

+
+typedef boost::ptr_vector<animal>  ptr_vec;
+ptr_vec vec;
+ptr_vec::iterator i = vec.begin();
+i->eat(); // no indirection needed
+
+
+
+

Sequence containers

+

The sequence containers used when you do not need to +keep an ordering on your elements. You can basically +expect all operations of the normal standard containers +to be available. So, for example, with a ptr_deque +and ptr_list object you can say:

+
+boost::ptr_deque<animal> deq;
+deq.push_front( new animal );    
+deq.pop_front();
+
+

because std::deque and std::list has push_front() +and pop_front members.

+

If the standard sequence support +random access, so does the pointer container; for example:

+
+for( boost::ptr_deque<animal>::size_type i = 0u;
+     i != deq.size(); ++i )
+     deq[i].eat();
+
+

The `ptr_vector also allows you to specify the size of +the buffer to allocate; for example

+
+boost::ptr_vector<animal> animals( 10u );
+
+

will reserve room for 10 animals.

+
+
+

Associative containers

+

To keep an ordering on our animals, we could use a ptr_set:

+
+boost::ptr_set<animal> set;
+set.insert( new monkey("bobo") );
+set.insert( new whale("anna") );
+...
+
+

This requires that operator<() is defined for animals. One +way to do this could be

+
+inline bool operator<( const animal& l, const animal& r )
+{
+    return l.name() < r.name();
+}
+
+

if we wanted to keep the animals sorted by name.

+

Maybe you want to keep all the animals in zoo ordered wrt. +their name, but it so happens that many animals have the +same name. We can then use a ptr_multimap:

+
+typedef boost::ptr_multimap<std::string,animal> zoo_type;
+zoo_type zoo;
+std::string bobo = "bobo",
+            anna = "anna";
+zoo.insert( bobo, new monkey(bobo) );
+zoo.insert( bobo, new elephant(bobo) );
+zoo.insert( anna, new whale(anna) );
+zoo.insert( anna, new emu(anna) );
+
+

Note that must create the key as an lvalue +(due to exception-safety issues); the following would not +have compiled

+
+zoo.insert( "bobo", // this is bad, but you get compile error
+            new monkey("bobo") );
+
+

If a multimap is not needed, we can use operator[]() +to avoid the clumsiness:

+
+boost::ptr_map<std::string,animal> animals;
+animals["bobo"].set_name("bobo");
+
+

This requires a default constructor for animals and +a function to do the initialization, in this case set_name();

+
+
+

Null values

+

By default, if you try to insert null into a container, an exception +is thrown. If you want to allow nulls, then you must +say so explicitly when declaring the container variable

+
+boost::ptr_vector< boost::nullable<animal> > animals_type;
+animals_type animals;
+...
+animals.insert( animals.end(), new dodo("fido") );
+animals.insert( animals.begin(), 0 ) // ok
+
+

Once you have inserted a null into the container, you must +always check if the value is null before accessing the object

+
+for( animals_type::iterator i = animals.begin();
+     i != animals.end(); ++i )
+{
+    if( !boost::is_null(i) ) // always check for validity
+        i->eat();
+}
+
+

If the container support random access, you may also check this as

+
+for( animals_type::size_type i = 0u; 
+     i != animals.size(); ++i )
+{
+    if( !animals.is_null(i) )
+         animals[i].eat();
+}
+
+

Note that it is meaningless to insert +null into ptr_set and ptr_multiset.

+
+
+

Clonability

+

In OO programming it is typical to prohibit copying of objects; the +objects may sometimes be allowed to be clonable; for example,:

+
+animal* animal::clone() const
+{
+    return do_clone(); // implemented by private virtual function
+}
+
+

If the OO hierarchy thus allows cloning, we need to tell the +pointer containers how cloning is to be done. This is simply +done by defining a free-standing function, new_clone(), +in the same namespace as +the object hierarchy:

+
+inline animal* new_clone( const animal& a )
+{
+    return a.clone();
+}
+
+

That is all, now a lot of functions in a pointer container +can exploit the clonability of the animal objects. For example

+
+typedef boost::ptr_list<animal> zoo_type;
+zoo_type zoo, another_zoo;
+...
+another_zoo.assign( zoo.begin(), zoo.end() );
+
+

will fill another zoo with clones of the first zoo. Similarly, +insert() can now insert clones into your pointer container

+
+another_zoo.insert( another_zoo.begin(), zoo.begin(), zoo.end() );
+
+

The whole container can now also be cloned

+
+zoo_type yet_another_zoo = zoo.clone();
+
+
+
+

New functions

+

Given that we know we are working with pointers, a few new functions +make sense. For example, say you want to remove an +animal from the zoo

+
+zoo_type::auto_type the_animal = zoo.release( zoo.begin() );
+the_animal->eat();
+animal* the_animal_ptr = the_animal.release(); // now this is not deleted
+zoo.release(2); // for random access containers
+
+

You can think of auto_type as a non-copyable form of +std::auto_ptr. Notice that when you release an object, the +pointer is removed from the container and the containers size +shrinks. You can also release the entire container if you +want to return it from a function

+
+boost::ptr_deque<animal> get_zoo()
+{
+    boost::ptr_deque<animal>  result;
+    ...
+    return result.release(); // give up ownership
+}
+...
+boost::ptr_deque<animal> animals = get_zoo();    
+
+

Let us assume we want to move an animal object from +one zoo to another. In other words, we want to move the +animal and the responsibility of it to another zoo

+
+another_zoo.transfer( another_zoo.end(), // insert before end 
+                      zoo.begin(),       // insert this animal ...
+                      zoo );             // from this container
+
+

This kind of "move-semantics" is different from +normal value-based containers. You can think of transfer() +as the same as splice() on std::list.

+

If you want to replace an element, you can easily do so

+
+zoo_type::auto_type old_animal = zoo.replace( zoo.begin(), new monkey("bibi") ); 
+zoo.replace( 2, old_animal.release() ); // for random access containers
+
+

A map is a little different to iterator over than normal standard maps. +Now we say

+
+typedef boost::ptr_map<std::String, boost::nullable<animal> > animal_map;
+animal_map map;
+...
+for( animal_map::iterator i = map.begin();
+     i != map.end(); ++i )
+{
+    std::cout << "\n key: " << i.key();
+    std::cout << "\n age: ";
+    
+    if( boost::is_null(i) )
+        std::cout << "unknown";
+    else
+        std::cout << i->age(); 
+ }
+
+

Maps can also be indexed with bounds-checking

+
+try
+{
+    animal& bobo = map.at("bobo");
+}
+catch( boost::bad_ptr_container_operation& e )
+{
+    // "bobo" not found
+}        
+
+

That is all; now you have learned all the basics!

+

Navigate

+
+ +
+
+
+ + diff --git a/doc/tutorial.rst b/doc/tutorial.rst new file mode 100755 index 0000000..2189c93 --- /dev/null +++ b/doc/tutorial.rst @@ -0,0 +1,333 @@ +======== +Tutorial +======== + +The tutorial shows you the most simple usage of the +library. It is assumed that the reader is familiar +with the use of standard containers. Although +the tutorial is devided into sections, it is recommended +that you read it all from top to bottom. + +* `Basic usage`_ +* `Indirected interface`_ +* `Sequence containers`_ +* `Associative containers`_ +* `Null values`_ +* `Clonability`_ +* `New functions`_ + +Basic usage +----------- + +The most important aspect of a pointer container is that it manages +memory for you. This means that you in most cases do not need to worry +about deleting memory. + +Let us assume that we have an OO-hierarchy of animals + +.. parsed-literal:: + + class animal : `boost::noncopyable `_ + { + public: + virtual ~animal() {} + void eat(); + // ... + }; + + class mammal : public animal + { + // ... + }; + + class bird : public animal + { + // ... + }; + + +Then the managing of the animals is straight-forward. Imagine a +Zoo:: + + class zoo + { + boost::ptr_vector the_animals; + public: + + void add_animal( animal* a ) + { + the_animals.push_back( a ); + } + }; + +Notice how just pass the class name to the container; there +is no ``*`` to indicate it is a pointer. +With this declaration we can now say:: + + zoo the_zoo; + the_zoo.add_animal( new mammal("joe") ); + the_zoo.add_animal( new bird("dodo") ); + +Thus we heap-allocate all elements of the container +and never rely on copy-semantics. + +Indirected interface +-------------------- + +As particular feature of the pointer containers is that +the query interface is indirected. For example, :: + + boost::ptr_vector vec; + vec.push_back( new animal ); // you add it as pointer ... + vec[0].eat(); // but get a reference back + +This indirection also happens to iterators, so :: + + typedef std::vector std_vec; + std_vec vec; + ... + std_vec::iterator i = vec.begin(); + (*i)->eat(); // '*' needed + +now becomes :: + + typedef boost::ptr_vector ptr_vec; + ptr_vec vec; + ptr_vec::iterator i = vec.begin(); + i->eat(); // no indirection needed + + +Sequence containers +------------------- + +The sequence containers used when you do not need to +keep an ordering on your elements. You can basically +expect all operations of the normal standard containers +to be available. So, for example, with a ``ptr_deque`` +and ``ptr_list`` object you can say:: + + boost::ptr_deque deq; + deq.push_front( new animal ); + deq.pop_front(); + +because ``std::deque`` and ``std::list`` has ``push_front()`` +and ``pop_front`` members. + +If the standard sequence support +random access, so does the pointer container; for example:: + + for( boost::ptr_deque::size_type i = 0u; + i != deq.size(); ++i ) + deq[i].eat(); + +The ```ptr_vector`` also allows you to specify the size of +the buffer to allocate; for example :: + + boost::ptr_vector animals( 10u ); + +will reserve room for 10 animals. + +Associative containers +---------------------- + +To keep an ordering on our animals, we could use a ``ptr_set``:: + + boost::ptr_set set; + set.insert( new monkey("bobo") ); + set.insert( new whale("anna") ); + ... + +This requires that ``operator<()`` is defined for animals. One +way to do this could be :: + + inline bool operator<( const animal& l, const animal& r ) + { + return l.name() < r.name(); + } + +if we wanted to keep the animals sorted by name. + +Maybe you want to keep all the animals in zoo ordered wrt. +their name, but it so happens that many animals have the +same name. We can then use a ``ptr_multimap``:: + + typedef boost::ptr_multimap zoo_type; + zoo_type zoo; + std::string bobo = "bobo", + anna = "anna"; + zoo.insert( bobo, new monkey(bobo) ); + zoo.insert( bobo, new elephant(bobo) ); + zoo.insert( anna, new whale(anna) ); + zoo.insert( anna, new emu(anna) ); + +Note that must create the key as an lvalue +(due to exception-safety issues); the following would not +have compiled :: + + zoo.insert( "bobo", // this is bad, but you get compile error + new monkey("bobo") ); + +If a multimap is not needed, we can use ``operator[]()`` +to avoid the clumsiness:: + + boost::ptr_map animals; + animals["bobo"].set_name("bobo"); + +This requires a default constructor for animals and +a function to do the initialization, in this case ``set_name()``; + +Null values +----------- + +By default, if you try to insert null into a container, an exception +is thrown. If you want to allow nulls, then you must +say so explicitly when declaring the container variable :: + + boost::ptr_vector< boost::nullable > animals_type; + animals_type animals; + ... + animals.insert( animals.end(), new dodo("fido") ); + animals.insert( animals.begin(), 0 ) // ok + +Once you have inserted a null into the container, you must +always check if the value is null before accessing the object :: + + for( animals_type::iterator i = animals.begin(); + i != animals.end(); ++i ) + { + if( !boost::is_null(i) ) // always check for validity + i->eat(); + } + +If the container support random access, you may also check this as :: + + for( animals_type::size_type i = 0u; + i != animals.size(); ++i ) + { + if( !animals.is_null(i) ) + animals[i].eat(); + } + +Note that it is meaningless to insert +null into ``ptr_set`` and ``ptr_multiset``. + +Clonability +----------- + +In OO programming it is typical to prohibit copying of objects; the +objects may sometimes be allowed to be clonable; for example,:: + + animal* animal::clone() const + { + return do_clone(); // implemented by private virtual function + } + +If the OO hierarchy thus allows cloning, we need to tell the +pointer containers how cloning is to be done. This is simply +done by defining a free-standing function, ``new_clone()``, +in the same namespace as +the object hierarchy:: + + inline animal* new_clone( const animal& a ) + { + return a.clone(); + } + +That is all, now a lot of functions in a pointer container +can exploit the clonability of the animal objects. For example :: + + typedef boost::ptr_list zoo_type; + zoo_type zoo, another_zoo; + ... + another_zoo.assign( zoo.begin(), zoo.end() ); + +will fill another zoo with clones of the first zoo. Similarly, +insert() can now insert clones into your pointer container :: + + another_zoo.insert( another_zoo.begin(), zoo.begin(), zoo.end() ); + +The whole container can now also be cloned :: + + zoo_type yet_another_zoo = zoo.clone(); + + +New functions +------------- + +Given that we know we are working with pointers, a few new functions +make sense. For example, say you want to remove an +animal from the zoo :: + + zoo_type::auto_type the_animal = zoo.release( zoo.begin() ); + the_animal->eat(); + animal* the_animal_ptr = the_animal.release(); // now this is not deleted + zoo.release(2); // for random access containers + +You can think of ``auto_type`` as a non-copyable form of +``std::auto_ptr``. Notice that when you release an object, the +pointer is removed from the container and the containers size +shrinks. You can also release the entire container if you +want to return it from a function :: + + boost::ptr_deque get_zoo() + { + boost::ptr_deque result; + ... + return result.release(); // give up ownership + } + ... + boost::ptr_deque animals = get_zoo(); + +Let us assume we want to move an animal object from +one zoo to another. In other words, we want to move the +animal and the responsibility of it to another zoo :: + + another_zoo.transfer( another_zoo.end(), // insert before end + zoo.begin(), // insert this animal ... + zoo ); // from this container + +This kind of "move-semantics" is different from +normal value-based containers. You can think of ``transfer()`` +as the same as ``splice()`` on ``std::list``. + +If you want to replace an element, you can easily do so :: + + zoo_type::auto_type old_animal = zoo.replace( zoo.begin(), new monkey("bibi") ); + zoo.replace( 2, old_animal.release() ); // for random access containers + +A map is a little different to iterator over than normal standard maps. +Now we say :: + + typedef boost::ptr_map > animal_map; + animal_map map; + ... + for( animal_map::iterator i = map.begin(); + i != map.end(); ++i ) + { + std::cout << "\n key: " << i.key(); + std::cout << "\n age: "; + + if( boost::is_null(i) ) + std::cout << "unknown"; + else + std::cout << i->age(); + } + +Maps can also be indexed with bounds-checking :: + + try + { + animal& bobo = map.at("bobo"); + } + catch( boost::bad_ptr_container_operation& e ) + { + // "bobo" not found + } + +That is all; now you have learned all the basics! + +**Navigate** + + - `home `_ + - `examples `_ + diff --git a/index.html b/index.html new file mode 100755 index 0000000..ab22cfb --- /dev/null +++ b/index.html @@ -0,0 +1,17 @@ + + + + + + +Boost.Smart Container Documentation + + + + +Automatic redirection failed, please go to +doc/smart_container.html + + + + diff --git a/test/Jamfile b/test/Jamfile new file mode 100755 index 0000000..9d9665e --- /dev/null +++ b/test/Jamfile @@ -0,0 +1,33 @@ + +subproject libs/smart_container/test ; + +import testing ; + +rule sc-test ( name ) +{ + return [ + run $(name).cpp + ../../test/build/boost_unit_test_framework + : : : $(BOOST_ROOT)/../boost_1_32_0 + ] + ; +} + + +test-suite smart-container : + [ sc-test ptr_vector ] + [ sc-test ptr_list ] + [ sc-test ptr_deque ] + [ sc-test ptr_set ] + [ sc-test ptr_map ] + [ sc-test ptr_array ] +# [ sc-test simple_test ] + [ sc-test tree_test ] + [ sc-test pointainer_speed ] + [ sc-test incomplete_type_test ] + [ sc-test view_example ] +# [ sc-test ptr_container_adapter ] +# [ sc-test ptr_map_adapter ] + [ sc-test tut1 ] + [ sc-test indirect_fun ] + ; diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 new file mode 100755 index 0000000..2d0799c --- /dev/null +++ b/test/Jamfile.v2 @@ -0,0 +1,9 @@ +project boost/ptr_container/doc ; + +import boostbook : boostbook ; +import doxygen ; + +boostbook doc : ptr_container.xml ; + + + diff --git a/test/algo_test_data.hpp b/test/algo_test_data.hpp new file mode 100755 index 0000000..6200a20 --- /dev/null +++ b/test/algo_test_data.hpp @@ -0,0 +1,37 @@ + +#include +#include + +template< typename C, typename T > +void value_algo_test(); + +template< typename C, typename T > +void polymorphic_algo_test(); + +template< typename C > +auto_ptr data(); + + +template< typename C, typename T > +void value_algo_test() +{ + //std::copy( + //std::swap + //std::transform + //std::replace + //std::reverse + //std::partition + //std::sort +} + + + +template< typename C, typename T > +void polymorphic_algo_test() +{ + //std::reverse( c.ptr_begin(), c.ptr_end() ); + //std::partition + //std::sort +} + + diff --git a/test/associative_test_data.hpp b/test/associative_test_data.hpp new file mode 100755 index 0000000..0a81b3a --- /dev/null +++ b/test/associative_test_data.hpp @@ -0,0 +1,125 @@ + +#include "test_data.hpp" +#include +#include + +template< typename C, typename B, typename T > +void ptr_set_test(); + +template< typename C, typename B, typename T > +void ptr_set_test() +{ + using namespace boost; + + BOOST_MESSAGE( "starting associative container test" ); + enum { max_cnt = 10, size = 100 }; + C c; + BOOST_CHECK( c.size() == 0 ); + + const C c2( c.begin(), c.end() ); + BOOST_CHECK( c.size() == c2.size() ); + + C c3; + + BOOST_MESSAGE( "finished construction test" ); + + BOOST_DEDUCED_TYPENAME C::allocator_type alloc = c.get_allocator(); + BOOST_DEDUCED_TYPENAME C::iterator i = c.begin(); + BOOST_DEDUCED_TYPENAME C::const_iterator ci = c2.begin(); + BOOST_DEDUCED_TYPENAME C::iterator i2 = c.end(); + BOOST_DEDUCED_TYPENAME C::const_iterator ci2 = c2.begin(); + BOOST_DEDUCED_TYPENAME C::reverse_iterator ri = c.rbegin(); + BOOST_DEDUCED_TYPENAME C::const_reverse_iterator cri = c2.rbegin(); + BOOST_DEDUCED_TYPENAME C::reverse_iterator rv2 = c.rend(); + BOOST_DEDUCED_TYPENAME C::const_reverse_iterator cvr2 = c2.rend(); + + BOOST_DEDUCED_TYPENAME C::ptr_iterator ptr_i = c.ptr_begin(); + BOOST_DEDUCED_TYPENAME C::ptr_const_iterator ptr_ci = c2.ptr_begin(); + BOOST_DEDUCED_TYPENAME C::ptr_iterator ptr_i2 = c.ptr_end(); + BOOST_DEDUCED_TYPENAME C::ptr_const_iterator ptr_ci2 = c2.ptr_begin(); + BOOST_DEDUCED_TYPENAME C::ptr_reverse_iterator ptr_ri = c.ptr_rbegin(); + BOOST_DEDUCED_TYPENAME C::ptr_const_reverse_iterator ptr_cri = c2.ptr_rbegin(); + BOOST_DEDUCED_TYPENAME C::ptr_reverse_iterator ptr_rv2 = c.ptr_rend(); + BOOST_DEDUCED_TYPENAME C::ptr_const_reverse_iterator ptr_cvr2 = c2.ptr_rend(); + + BOOST_MESSAGE( "finished iterator test" ); + + BOOST_DEDUCED_TYPENAME C::size_type s = c.size(); + BOOST_DEDUCED_TYPENAME C::size_type s2 = c.max_size(); + BOOST_CHECK_EQUAL( c.size(), s ); + bool b = c.empty(); + BOOST_MESSAGE( "finished accessors test" ); + + T* t = new T; + c.insert( c.end(), t ); +// c.insert( c.end(), T() ); + c.insert( new T ); + c3.insert( c.begin(), c.end() ); + c.erase( c.begin() ); + c3.erase( c3.begin(), c3.end() ); + + BOOST_CHECK( c3.empty() ); + c.swap( c3 ); + BOOST_CHECK( !c3.empty() ); + c3.clear(); + BOOST_CHECK( c3.empty() ); + BOOST_MESSAGE( "finished modifiers test" ); + + c.insert( c.end(), new T ); + typename C::auto_type ptr2 = c.release( c.begin() ); + std::auto_ptr ap = c.release(); + c = c2.clone(); + BOOST_MESSAGE( "finished release/clone test" ); + + c3.insert( new T ); + c3.insert( new T ); + BOOST_CHECK_EQUAL( c3.size(), 2u ); + c.transfer( c3.begin(), c3 ); + BOOST_CHECK( c3.empty() == false ); + c.transfer( c3.begin(), c3.end(), c3 ); + BOOST_CHECK( c3.empty() ); + BOOST_CHECK( !c.empty() ); + c3.transfer( c ); + BOOST_CHECK( !c3.empty() ); + BOOST_CHECK( c.empty() ); + BOOST_MESSAGE( "finished transfer test" ); + + C c4; + c4.swap(c3); + swap(c4,c3); + BOOST_MESSAGE( "finished set/map interface test" ); + + sub_range sub; + sub_range csub; + + i = c.find( T() ); + ci = c2.find( T() ); + c2.count( T() ); + i = c.lower_bound( T() ); + ci = c2.lower_bound( T() ); + i = c.upper_bound( T() ); + ci = c2.upper_bound( T() ); + sub = c.equal_range( T() ); + csub = c2.equal_range( T() ); + + //BOOST_CHECK_THROW( c.at( T() ), bad_ptr_container_operation ); + //BOOST_CHECK_THROW( c2.at( T() ), bad_ptr_container_operation ); + + try + { + c.at( T() ); + } + catch( const bad_ptr_container_operation& ) + { } + + try + { + c2.at( T() ); + } + catch( const bad_ptr_container_operation& ) + { } + + + BOOST_MESSAGE( "finished algorithms interface test" ); +} + diff --git a/test/cast.cpp b/test/cast.cpp new file mode 100755 index 0000000..fd22912 --- /dev/null +++ b/test/cast.cpp @@ -0,0 +1,6 @@ +int main() +{ + void * p = 0; + void*& rp = p; + int*& p2 = *static_cast( &rp ); +} diff --git a/test/concept_check_data.hpp b/test/concept_check_data.hpp new file mode 100755 index 0000000..174125f --- /dev/null +++ b/test/concept_check_data.hpp @@ -0,0 +1,12 @@ + +template< typename C, typename T > +void typedef_test(); + + + +template< typename C, typename T > +void typedef_test() +{ +} + + diff --git a/test/convert.cpp b/test/convert.cpp new file mode 100755 index 0000000..eed0f16 --- /dev/null +++ b/test/convert.cpp @@ -0,0 +1,36 @@ +template< class Iter, int Level > +struct iterator +{ + typedef Iter type; + typedef iterator next; + + next::type& next; + mutable Iter iter_; + + + Iter& base() const + { + return iter_; + } +}; + +template< class Iter, class Boxed > +Iter unbox( const Boxed& b ) +{ + +} + +#include + +int main() +{ + std::vector v; + typedef std::vector::iterator iter; + + iterator i; + iter ii = i; + + iterator< iterator > iii; + iter iiii = iii; +} + diff --git a/test/incomplete_type_test.cpp b/test/incomplete_type_test.cpp new file mode 100755 index 0000000..ac0581b --- /dev/null +++ b/test/incomplete_type_test.cpp @@ -0,0 +1,176 @@ + +#include "test_data.hpp" +#include +#include +#include +#include + +using namespace std; +using namespace boost; + +// +// Forward declare 'allocate_clone()' to be able +// use clonability of 'Composite' inline in the class. +// This is normally not needed when using .hpp + .cpp files. +// +class Composite; +Composite* new_clone( const Composite& ); + + +class Composite +{ + typedef ptr_vector composite_t; + typedef composite_t::iterator iterator; + typedef composite_t::const_iterator const_iterator; + typedef composite_t::size_type size_type; + composite_t elements_; + + // + // only used internally for 'clone()' + // + Composite( const Composite& r ) : elements_( r.elements_.clone() ) + { } + + // + // this class is not Copyable nor Assignable + // + void operator=( const Composite& ); + +public: + Composite() + { } + + // + // of course detructor is virtual + // + virtual ~Composite() + { } + + // + // one way of adding new elements + // + void add( Composite* c ) + { + elements_.push_back( c ); + } + + // + // second way of adding new elements + // + void add( Composite& c ) + { + elements_.push_back( new_clone( c ) ); + } + + void remove( iterator where ) + { + elements_.erase( where ); + } + + // + // recusively count the elements + // + size_type size() const + { + size_type res = 0; + for( const_iterator i = elements_.begin(); i != elements_.end(); ++i ) + res += i->size(); + return 1 /* this */ + res; + } + + void foo() + { + do_foo(); + for( iterator i = elements_.begin(); i != elements_.end(); ++i ) + i->foo(); + } + + // + // this class is clonable and this is the callback for 'allocate_clone()' + // + Composite* clone() const + { + return do_clone(); + } + +private: + virtual void do_foo() + { + cout << "composite base" << "\n"; + } + + virtual Composite* do_clone() const + { + return new Composite( *this ); + } +}; + +// +// make 'Composite' clonable; note that we do not need to overload +// the function in the 'boost' namespace. +// +Composite* new_clone( const Composite& c ) +{ + return c.clone(); +} + + +class ConcreteComposite1 : public Composite +{ + virtual void do_foo() + { + cout << "composite 1" << "\n"; + } + + virtual Composite* do_clone() const + { + return new ConcreteComposite1(); + } +}; + + +class ConcreteComposite2 : public Composite +{ + virtual void do_foo() + { + cout << "composite 2" << "\n"; + } + + virtual Composite* clone() const + { + return new ConcreteComposite2(); + } +}; + +void test_incomplete() +{ + Composite c; + c.add( new ConcreteComposite1 ); + c.add( new ConcreteComposite2 ); + BOOST_CHECK_EQUAL( c.size(), 3 ); + c.add( new_clone( c ) ); // add c to itself + BOOST_CHECK_EQUAL( c.size(), 6 ); + c.add( c ); // add c to itself + BOOST_CHECK_EQUAL( c.size(), 12 ); + c.foo(); +} + +using namespace boost; + + +#include +using boost::unit_test::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite* test = BOOST_TEST_SUITE( "Smart Container Test Suite" ); + + test->add( BOOST_TEST_CASE( &test_incomplete ) ); + + return test; +} + +// +// todo: remake example with shared_ptr +// + diff --git a/test/indirect_fun.cpp b/test/indirect_fun.cpp new file mode 100755 index 0000000..6fb9823 --- /dev/null +++ b/test/indirect_fun.cpp @@ -0,0 +1,61 @@ + +#include +#include +#include +#include +#include +#include +#include + +bool lesser_than( const std::string& l, const std::string& r ) +{ + return l < r; +} + + +void test_fun() +{ + using namespace boost; + ptr_vector vec; + + indirect_fun< std::less > fun; + + std::string* ptr1 = new std::string("bar"); + std::string* ptr2 = new std::string("foo"); + BOOST_CHECK( fun( ptr1, ptr2 ) == true ); + + void* vptr1 = ptr1; + void* vptr2 = ptr2; + void_ptr_indirect_fun< std::less, std::string> cast_fun; + BOOST_CHECK( cast_fun( vptr1, vptr2 ) == true ); + + assign::push_back( vec )( new std::string("aa") ) + ( new std::string("bb") ) + ( new std::string("dd") ) + ( new std::string("cc") ) + ( new std::string("a") ); + + std::sort( vec.ptr_begin(), vec.ptr_end(), fun ); + BOOST_CHECK( vec[0] == "a" ); + BOOST_CHECK( vec[4] == "dd" ); + + std::sort( vec.ptr_begin(), vec.ptr_end(), + make_indirect_fun( &lesser_than ) ); + BOOST_CHECK( vec[1] == "aa" ); + BOOST_CHECK( vec[2] == "bb" ); + +} + +#include +using boost::unit_test::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite* test = BOOST_TEST_SUITE( "Smart Container Test Suite" ); + + test->add( BOOST_TEST_CASE( &test_fun ) ); + + return test; +} + + diff --git a/test/indirect_vector.cpp b/test/indirect_vector.cpp new file mode 100755 index 0000000..d1ec256 --- /dev/null +++ b/test/indirect_vector.cpp @@ -0,0 +1,109 @@ +#include +#include +#include +#include + +struct copy_clone_allocator +{ + template< class T > + T allocate_clone( const T& r ) + { + return r; + } + + template< class T > + void deallocate_clone( const T* ) + { + // do nothing + } +}; + + +template< class T > +struct indirect_value +{ + typedef typename boost::iterator_value::type type; +}; + + +template +< + class T, + class CloneAllocator = copy_clone_allocator, + class Allocator = std::allocator +> +class indirect_vector +{ + typedef std::vector vec; + vec vec_; + +public: + + typedef boost::indirect_iterator iterator; + typedef T value_type; + typedef typename indirect_value::type indirect_value; + typedef indirect_value& reference; + +public: + + void push_back( const T& r ) + { + vec_.push_back( r ); + } + + iterator begin() + { + return iterator( vec_.begin() ); + } + + iterator end() + { + return iterator( vec_.end() ); + } + + reference front() + { + return *begin(); + } + + reference back() + { + return *--end(); + } +}; + +template +< + class T, /* can be T, nullable or viewable + class CloneAllocator = /* link: see below */, + class Allocator = /* link: see below */ +> +class indirect_vector +{ + +}; + +indirect_vector< boost::viewable >; + byt om på policies (?) +indirect_vector< booot::nullable >; +indirect_vector< T >; + +indirect_vector< viewable< share_ptr > >; + + +#include +#include + +int main() +{ + using namespace boost; + typedef std::vector::iterator iter_t; + indirect_vector vec; + indirect_vector vec2; + std::vector source; + source.push_back( 5 ); + vec.push_back( source.begin() ); + vec.front() = 5; + assert( vec.front() == 5 ); + assert( *vec.begin() == 5 ); +} + diff --git a/test/map_value_iterator.cpp b/test/map_value_iterator.cpp new file mode 100755 index 0000000..92b3334 --- /dev/null +++ b/test/map_value_iterator.cpp @@ -0,0 +1,118 @@ +#include + +template< class Map > +struct select_first +{ + typedef typename Map::key_type& result_type; + + result_type operator()( const typename Map::value_type& r ) const + { + return r.first; + } +}; + +template< class Map > +struct select_second +{ + typedef typename Map::mapped_type& result_type; + + result_type operator()( const typename Map::value_type& r ) const + { + return r.second; + } +}; + +template< class Map > +struct map_key_iterator : + public boost::transform_iterator< select_first, + typename Map::const_iterator > +{ +private: + typedef boost::transform_iterator< select_first, + typename Map::const_iterator > + base; + + typedef typename Map::const_iterator iterator; +public: + map_key_iterator() : base() + { } + + map_key_iterator( iterator x ) : base(x) + { } + + map_key_iterator& operator=( iterator r ) + { + base::operator=(r); + return *this; + } +}; + + +template< class Map > +struct map_value_iterator : + public boost::transform_iterator< select_second, + typename Map::iterator > +{ +private: + typedef boost::transform_iterator< select_second, + typename Map::iterator > + base; + typedef typename Map::iterator iterator; + +public: + map_value_iterator() : base() + { } + + map_value_iterator( iterator x ) : base(x) + { } + + map_value_iterator& operator=( iterator r ) + { + base::operator=(r); + return *this; + } + +}; + + +template< class Map > +struct map_const_value_iterator : + public boost::transform_iterator< select_second, + typename Map::const_iterator > +{ +private: + typedef boost::transform_iterator< select_second, + typename Map::const_iterator > + base; + typedef typename Map::const_iterator iterator; +public: + map_const_value_iterator() : base() + { } + + map_const_value_iterator( iterator x ) : base(x) + { } + + map_const_value_iterator& operator=( iterator r ) + { + base::operator=(r); + return *this; + } +}; + +#include + +int main() +{ + typedef std::map map; + + map m; + map_key_iterator key_begin = m.begin(); + map_value_iterator value_begin = m.begin(); + map_const_value_iterator value_end = m.end(); + + key_begin++; + value_begin++; + value_end--; +} + + diff --git a/test/null_object.cpp b/test/null_object.cpp new file mode 100755 index 0000000..8f07fcc --- /dev/null +++ b/test/null_object.cpp @@ -0,0 +1,243 @@ + +#include +#include +#include +#include +#include +#include +#include + + +class animal +{ + virtual std::string do_speak() const = 0; + std::string name_; + +protected: + // + // Animals cannot be copied... + // + animal( const animal& r ) : name_( r.name_ ) { } + void operator=( const animal& ); + +private: + // + // ...but due to advances in genetics, we can clone them! + // + + virtual animal* do_clone() const = 0; + +public: + animal() : name_("") { } + animal( const std::string& name ) : name_(name) { } + virtual ~animal() { } + + std::string speak() const + { + return do_speak(); + } + + std::string name() const + { + return name_; + } + + animal* clone() const + { + return do_clone(); + } + + bool is_null() const; +}; + +animal* allocate_clone( const animal& a ) +{ + return a.clone(); +} + +// +// Define a null object with just about zero overhead. +// No matter how many null objects you have, you will always +// share the same static instance. +// +// This class must always be a leaf class, hence you should never derive +// from it. +// + +class null_animal : public boost::null_object +{ + virtual std::string do_speak() const { return ""; } + virtual animal* do_clone() const { return new null_animal; } +}; + +inline bool animal::is_null() const +{ + return this == &null_animal::null_instance; +} + + +template< class T > +inline bool is_null( T& r ) +{ + // &r == is_null::instance()? +} + + + +const std::string muuuh = "Muuuh!"; +const std::string oiink = "Oiiink"; + +class cow : public animal +{ + virtual std::string do_speak() const + { + return muuuh; + } + + virtual animal* do_clone() const + { + return new cow( *this ); + } + +public: + cow( const std::string& name ) : animal(name) { } +}; + +class pig : public animal +{ + virtual std::string do_speak() const + { + return oiink; + } + + virtual animal* do_clone() const + { + return new pig( *this ); + } + +public: + pig( const std::string& name ) : animal(name) { } +}; + + +int main() +{ + typedef boost::ptr_deque farm_t; + farm_t farm; + farm.push_back( new null_animal ); + farm.push_back( new pig("foo") ); + farm.push_back( new null_animal ); + farm.push_back( new cow("bar") ); + farm.push_back( new null_animal ); + + for( farm_t::iterator i = farm.begin(), e = farm.end(); + i != e; ++i ) + { + std::cout << i->name() << " says " << i->speak(); + } + + farm_t farm2( farm.begin(), farm.end() ); + + for( farm_t::iterator i = farm2.begin(), e = farm2.end(); + i != e; ++i ) + { + std::cout << i->name() << " says " << i->speak(); + } + + const int count = 1000000; + typedef std::deque ptr_deque; + + { + ptr_deque d; + d.push_back( 0 ); + d.push_back( new pig("foo") ); + d.push_back( 0 ); + d.push_back( new cow("bar") ); + d.push_back( 0 ); + + boost::progress_timer timer; + for( int i = 0; i != count; ++i ) + for( ptr_deque::iterator i = d.begin(), e = d.end(); + i != e; + ++i ) + { + if( *i ) + { + ( *i )->name(); + ( *i )->speak(); + } + } + } + + { + boost::progress_timer timer; + + for( int i = 0; i != count; ++i ) + for( farm_t::iterator i = farm2.begin(), e = farm2.end(); + i != e; ++i ) + { + i->name(); + i->speak(); + } + } + + { + ptr_deque d; + d.push_back( 0 ); + d.push_back( new pig("foo") ); + d.push_back( new cow("foo bar") ); + d.push_back( new cow("bar") ); + d.push_back( 0 ); + + boost::progress_timer timer; + for( int i = 0; i != count; ++i ) + for( ptr_deque::iterator i = d.begin(), e = d.end(); + i != e; + ++i ) + { + if( *i ) + { + ( *i )->name(); + ( *i )->speak(); + } + } + } + + { + ptr_deque d; + d.push_back( 0 ); + d.push_back( new pig("foo") ); + d.push_back( new cow("foo bar") ); + d.push_back( new pig("bar") ); + d.push_back( new cow("barbar") ); + + boost::progress_timer timer; + for( int i = 0; i != count; ++i ) + for( ptr_deque::iterator i = d.begin(), e = d.end(); + i != e; + ++i ) + { + if( *i ) + { + ( *i )->name(); + ( *i )->speak(); + } + } + } + + { + boost::progress_timer timer; + + for( int i = 0; i != count; ++i ) + for( farm_t::iterator i = farm2.begin(), e = farm2.end(); + i != e; ++i ) + { + if( !i->is_null() ) + { + i->name(); + i->speak(); + } + } + } + +} diff --git a/test/pointainer_speed.cpp b/test/pointainer_speed.cpp new file mode 100755 index 0000000..0a2bb9b --- /dev/null +++ b/test/pointainer_speed.cpp @@ -0,0 +1,194 @@ +#include "test_data.hpp" +#include +#include +#include + + +using namespace boost; +using namespace std; + + +typedef shared_ptr PolyPtr; + +struct PolyPtrOps +{ + void operator()( const PolyPtr& a ) + { a->foo(); } +}; + +struct less_than +{ + bool operator()( const PolyPtr& l, const PolyPtr& r ) const + { + return *l < *r; + } + + bool operator()( const Base* l, const Base* r ) const + { + return *l < *r; + } +}; + +struct greater_than +{ + bool operator()( const PolyPtr& l, const PolyPtr& r ) const + { + return *l > *r; + } + + bool operator()( const Base* l, const Base* r ) const + { + return *l > *r; + } +}; + +struct data_less_than +{ + bool operator()( const PolyPtr& l, const PolyPtr& r ) const + { + return l->data_less_than(*r); + } + + bool operator()( const Base* l, const Base* r ) const + { + return l->data_less_than(*r); + } +}; + +struct data_less_than2 +{ + bool operator()( const PolyPtr& l, const PolyPtr& r ) const + { + return l->data_less_than2(*r); + } + + bool operator()( const Base* l, const Base* r ) const + { + return l->data_less_than2(*r); + } +}; + + +void test_speed() +{ + enum { size = 50000 }; + vector svec; + ptr_vector pvec; + + { + progress_timer timer; + for( int i = 0; i < size; ++i ) + svec.push_back( PolyPtr( new Derived ) ); + cout << "\n shared_ptr call new: "; + } + + { + progress_timer timer; + for( int i = 0; i < size; ++i ) + pvec.push_back( new Derived ); + cout << "\n smart container call new: "; + } + + { + progress_timer timer; + for_each( svec.begin(), svec.end(), PolyPtrOps() ); + cout << "\n shared_ptr call foo(): "; + } + + { + progress_timer timer; + for_each( pvec.begin(), pvec.end(), mem_fun_ref( &Base::foo ) ); + cout << "\n smart container call foo(): "; + } + + { + progress_timer timer; + sort( svec.begin(), svec.end(), less_than() ); + cout << "\n shared_ptr call sort(): "; + } + + { + progress_timer timer; + sort( pvec.ptr_begin(), pvec.ptr_end(), less_than() ); + cout << "\n smart container call sort(): "; + } + + { + progress_timer timer; + sort( svec.begin(), svec.end(), greater_than() ); + cout << "\n shared_ptr call sort() #2: "; + } + + { + progress_timer timer; + sort( pvec.ptr_begin(), pvec.ptr_end(), greater_than() ); + cout << "\n smart container call sort() #2: "; + } + + { + progress_timer timer; + sort( svec.begin(), svec.end(), data_less_than() ); + cout << "\n shared_ptr call sort() #3: "; + } + + { + progress_timer timer; + sort( pvec.ptr_begin(), pvec.ptr_end(), data_less_than() ); + cout << "\n smart container call sort() #3: "; + } + + { + progress_timer timer; + sort( svec.begin(), svec.end(), data_less_than2() ); + cout << "\n shared_ptr call sort() #4: "; + } + + { + progress_timer timer; + sort( pvec.ptr_begin(), pvec.ptr_end(), data_less_than2() ); + cout << "\n smart container call sort() #4: "; + } + + vector copy1; + for( ptr_vector::ptr_iterator i = pvec.ptr_begin(); i != pvec.ptr_end(); ++ i ) + copy1.push_back( *i ); + + sort( pvec.ptr_begin(), pvec.ptr_end() ); + + + vector copy2; + for( ptr_vector::ptr_iterator i = pvec.ptr_begin(); i != pvec.ptr_end(); ++ i ) + copy2.push_back( *i ); + + + for( unsigned int i = 0; i < copy1.size(); ++i ) + { + bool found = false; + for( int j = 0; j < copy1.size(); ++ j ) + if( copy1[i] == copy2[j] ) + found = true; + + if( !found ) + cout << copy1[i] << endl; + } + + assert( pvec.size() == size ); + cout << endl; +} + + +#include +using boost::unit_test::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite* test = BOOST_TEST_SUITE( "Smart Container Test Suite" ); + + test->add( BOOST_TEST_CASE( &test_speed ) ); + + return test; +} + + + + diff --git a/test/ptr_array.cpp b/test/ptr_array.cpp new file mode 100755 index 0000000..9bd9cdd --- /dev/null +++ b/test/ptr_array.cpp @@ -0,0 +1,157 @@ +#include "test_data.hpp" +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace boost; + +template< class Node, size_t N > +class n_ary_tree : boost::noncopyable +{ + typedef n_ary_tree this_type; + typedef ptr_array tree_t; + + tree_t tree; + Node data; + +public: + n_ary_tree() { } + n_ary_tree( const Node& r ) : data(r) { } + +public: // modifers + void set_data( const Node& r ) { data = r; } + template< size_t idx > + void set_child( this_type* r ) { tree. BOOST_NESTED_TEMPLATE replace(r); } + +public: // accessors + void print( std::ostream&, std::string indent = " " ); + template< size_t idx > + this_type& child() { return tree. BOOST_NESTED_TEMPLATE at(); } + template< size_t idx > + const this_type& child() const { return tree. BOOST_NESTED_TEMPLATE at(); } + +}; + + + +template< class Node, size_t N > +void n_ary_tree::print( std::ostream& out, std::string indent ) +{ + out << indent << data << "\n"; + indent += " "; + for( size_t i = 0; i != N; ++i ) + if( !tree.is_null(i) ) + tree[i].print( out, indent + " " ); +} + + +template< class C, class B, class T > +void test_array_interface(); + +void test_array() +{ + typedef n_ary_tree binary_tree; + binary_tree tree; + tree.set_data( "root" ); + tree.set_child<0>( new binary_tree( "left subtree" ) ); + tree.set_child<1>( new binary_tree( "right subtree" ) ); + binary_tree& left = tree.child<0>(); + left.set_child<0>( new binary_tree( "left left subtree" ) ); + left.set_child<1>( new binary_tree( "left right subtree" ) ); + binary_tree& right = tree.child<1>(); + right.set_child<0>( new binary_tree( "right left subtree" ) ); + right.set_child<1>( new binary_tree( "right right subtree" ) ); + + tree.print( std::cout ); + + test_array_interface,Base,Derived>(); + test_array_interface,10>,Base,Derived>(); + test_array_interface,Value,Value>(); + test_array_interface,10>,Value,Value>(); + + ptr_array vec; + BOOST_CHECK_THROW( vec.at(10), bad_ptr_container_operation ); + BOOST_CHECK_THROW( (vec.replace(10u, new int(0))), bad_ptr_container_operation ); + BOOST_CHECK_THROW( (vec.replace(0u, 0)), bad_ptr_container_operation ); + +} + +template< class C, class B, class T > +void test_array_interface() +{ + C c; + c.replace( 0, new T ); + c.replace( 1, new B ); + c.replace( 9, new T ); + const C c2( c.clone() ); + + BOOST_DEDUCED_TYPENAME C::iterator i = c.begin(); + BOOST_DEDUCED_TYPENAME C::const_iterator ci = c2.begin(); + BOOST_DEDUCED_TYPENAME C::iterator i2 = c.end(); + BOOST_DEDUCED_TYPENAME C::const_iterator ci2 = c2.begin(); + BOOST_DEDUCED_TYPENAME C::reverse_iterator ri = c.rbegin(); + BOOST_DEDUCED_TYPENAME C::const_reverse_iterator cri = c2.rbegin(); + BOOST_DEDUCED_TYPENAME C::reverse_iterator rv2 = c.rend(); + BOOST_DEDUCED_TYPENAME C::const_reverse_iterator cvr2 = c2.rend(); + + BOOST_DEDUCED_TYPENAME C::ptr_iterator ptr_i = c.ptr_begin(); + BOOST_DEDUCED_TYPENAME C::ptr_const_iterator ptr_ci = c2.ptr_begin(); + BOOST_DEDUCED_TYPENAME C::ptr_iterator ptr_i2 = c.ptr_end(); + BOOST_DEDUCED_TYPENAME C::ptr_const_iterator ptr_ci2 = c2.ptr_begin(); + BOOST_DEDUCED_TYPENAME C::ptr_reverse_iterator ptr_ri = c.ptr_rbegin(); + BOOST_DEDUCED_TYPENAME C::ptr_const_reverse_iterator ptr_cri = c2.ptr_rbegin(); + BOOST_DEDUCED_TYPENAME C::ptr_reverse_iterator ptr_rv2 = c.ptr_rend(); + BOOST_DEDUCED_TYPENAME C::ptr_const_reverse_iterator ptr_cvr2 = c2.ptr_rend(); + + BOOST_MESSAGE( "finished iterator test" ); + + BOOST_CHECK_EQUAL( c.empty(), false ); + BOOST_CHECK_EQUAL( c.size(), c.max_size() ); + + BOOST_MESSAGE( "finished capacity test" ); + + BOOST_CHECK_EQUAL( c.is_null(0), false ); + BOOST_CHECK_EQUAL( c.is_null(1), false ); + BOOST_CHECK_EQUAL( c.is_null(2), true ); + + c.front(); + c.back(); + c2.front(); + c2.back(); + C c3; + c.swap( c3 ); + C c4; + swap(c4,c3); + c3.swap(c4); + + BOOST_CHECK_EQUAL( c.is_null(0), true ); + BOOST_CHECK_EQUAL( c3.is_null(0), false ); + + c.replace( 5, new T ); + BOOST_CHECK_EQUAL( c.is_null(5), false ); + c = c3.release(); + for( size_t i = 0; i < c3.size(); ++i ) + BOOST_CHECK_EQUAL( c3.is_null(i), true ); + + BOOST_MESSAGE( "finished element access test" ); + +} + +#include +using boost::unit_test::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite* test = BOOST_TEST_SUITE( "Smart Container Test Suite" ); + + test->add( BOOST_TEST_CASE( &test_array ) ); + + return test; +} + + diff --git a/test/ptr_container_adapter.cpp b/test/ptr_container_adapter.cpp new file mode 100755 index 0000000..0a38f56 --- /dev/null +++ b/test/ptr_container_adapter.cpp @@ -0,0 +1,59 @@ + +#include "sequence_test_data.hpp" +#include "concept_check_data.hpp" +#include +#include + + +template< class T > +class my_list : public std::list +{ + typedef BOOST_DEDUCED_TYPENAME std::list base_class; + +public: +/* + my_list( const base_class::allocator_type& alloc = base_class::allocator_type() ) + : base_class( alloc ) {} + + my_list( size_type n, const T& x, const base_class::allocator_type& alloc = base_class::allocator_type() ) + : base_class( n, x, alloc ) {} + + template< class InputIterator > + my_list( InputIterator first, InputIterator last ) : base_class( first, last ) {} +*/ +}; + +void test_container_adapter() +{ + typedef ptr_container_adapter< my_list > base_ptr_list; + typedef ptr_container_adapter< my_list > value_ptr_list; + + typedef_test< base_ptr_list, Derived >(); + typedef_test< value_ptr_list, Value >(); + +// reversible_container_test< base_ptr_list, Base, Derived >(); +// reversible_container_test< value_ptr_list, Value, Value >(); + + base_ptr_list l; + l.push_back( new Derived ); + l.push_back( new Derived ); + +// algo_test< ptr_list, Value >(); +// algo_test_polymorphic< ptr_list, Derived >(); +} + +#include + +using boost::unit_test_framework::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite* test = BOOST_TEST_SUITE( "Smart Container Test Suite" ); + + test->add( BOOST_TEST_CASE( &test_container_adapter ) ); + + return test; +} + + + diff --git a/test/ptr_deque.cpp b/test/ptr_deque.cpp new file mode 100755 index 0000000..20d29bb --- /dev/null +++ b/test/ptr_deque.cpp @@ -0,0 +1,24 @@ + +#include "sequence_test_data.hpp" +#include + +void test_ptr_deque() +{ + reversible_container_test< ptr_deque, Base, Derived >(); + reversible_container_test< ptr_deque, Value, Value >(); + reversible_container_test< ptr_deque< nullable >, Base, Derived >(); + reversible_container_test< ptr_deque< nullable >, Value, Value >(); +} + +#include +using boost::unit_test::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite* test = BOOST_TEST_SUITE( "Smart Container Test Suite" ); + + test->add( BOOST_TEST_CASE( &test_ptr_deque ) ); + + return test; +} + diff --git a/test/ptr_list.cpp b/test/ptr_list.cpp new file mode 100755 index 0000000..0340648 --- /dev/null +++ b/test/ptr_list.cpp @@ -0,0 +1,27 @@ + +#include "sequence_test_data.hpp" +#include + +void test_list() +{ + reversible_container_test< ptr_list, Base, Derived >(); + reversible_container_test< ptr_list, Value, Value >(); + reversible_container_test< ptr_list< nullable >, Base, Derived >(); + reversible_container_test< ptr_list< nullable >, Value, Value >(); +} + +#include +using boost::unit_test::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite* test = BOOST_TEST_SUITE( "Smart Container Test Suite" ); + + test->add( BOOST_TEST_CASE( &test_list ) ); + + return test; +} + + + + diff --git a/test/ptr_map.cpp b/test/ptr_map.cpp new file mode 100755 index 0000000..ae0012e --- /dev/null +++ b/test/ptr_map.cpp @@ -0,0 +1,225 @@ + +#include "test_data.hpp" +#include +#include +#include +#include +#include +#include + +template< typename C, typename B, typename T > +void ptr_map_test(); + +template< class Key > +Key get_next_key( const Key& k ); + +template<> +int get_next_key( const int& ) +{ + return rand(); +} + +template<> +std::string get_next_key( const std::string& ) +{ + return boost::lexical_cast( rand() ); +} + + +template< typename C, typename B, typename T > +void ptr_map_test() +{ + BOOST_MESSAGE( "starting associative container test" ); + enum { max_cnt = 10, size = 100 }; + C c; + BOOST_CHECK( c.size() == 0 ); + + const C c2( c.begin(), c.end() ); + BOOST_CHECK( c.size() == c2.size() ); + + C c3; + + BOOST_MESSAGE( "finished construction test" ); + + BOOST_DEDUCED_TYPENAME C::allocator_type alloc = c.get_allocator(); + BOOST_DEDUCED_TYPENAME C::iterator i = c.begin(); + BOOST_DEDUCED_TYPENAME C::const_iterator ci = c2.begin(); + BOOST_DEDUCED_TYPENAME C::iterator i2 = c.end(); + BOOST_DEDUCED_TYPENAME C::const_iterator ci2 = c2.begin(); + BOOST_DEDUCED_TYPENAME C::reverse_iterator ri = c.rbegin(); + BOOST_DEDUCED_TYPENAME C::const_reverse_iterator cri = c2.rbegin(); + BOOST_DEDUCED_TYPENAME C::reverse_iterator rv2 = c.rend(); + BOOST_DEDUCED_TYPENAME C::const_reverse_iterator cvr2 = c2.rend(); + + BOOST_DEDUCED_TYPENAME C::ptr_iterator ptr_i = c.ptr_begin(); + BOOST_DEDUCED_TYPENAME C::ptr_const_iterator ptr_ci = c2.ptr_begin(); + BOOST_DEDUCED_TYPENAME C::ptr_iterator ptr_i2 = c.ptr_end(); + BOOST_DEDUCED_TYPENAME C::ptr_const_iterator ptr_ci2 = c2.ptr_begin(); + BOOST_DEDUCED_TYPENAME C::ptr_reverse_iterator ptr_ri = c.ptr_rbegin(); + BOOST_DEDUCED_TYPENAME C::ptr_const_reverse_iterator ptr_cri = c2.ptr_rbegin(); + BOOST_DEDUCED_TYPENAME C::ptr_reverse_iterator ptr_rv2 = c.ptr_rend(); + BOOST_DEDUCED_TYPENAME C::ptr_const_reverse_iterator ptr_cvr2 = c2.ptr_rend(); + BOOST_DEDUCED_TYPENAME C::key_type a_key; + + BOOST_MESSAGE( "finished iterator test" ); + + BOOST_DEDUCED_TYPENAME C::size_type s = c.size(); + BOOST_DEDUCED_TYPENAME C::size_type s2 = c.max_size(); + BOOST_CHECK_EQUAL( c.size(), s ); + bool b = c.empty(); + BOOST_MESSAGE( "finished accessors test" ); + + a_key = get_next_key( a_key ); + c.insert( a_key, new T ); + a_key = get_next_key( a_key ); + c.insert( a_key, new T ); + c3.insert( c.begin(), c.end() ); + c.insert( c3 ); + c.erase( c.begin() ); + c3.erase( c3.begin(), c3.end() ); + + BOOST_CHECK( c3.empty() ); + c.swap( c3 ); + swap(c,c3); + swap(c3,c); + BOOST_CHECK( !c3.empty() ); + c3.clear(); + BOOST_CHECK( c3.empty() ); + BOOST_MESSAGE( "finished modifiers test" ); + + + a_key = get_next_key( a_key ); + c.insert( a_key, new T ); + a_key = get_next_key( a_key ); + c.insert( a_key, new T ); + typename C::auto_type ptr2 = c.release( c.begin() ); + std::auto_ptr ap = c.release(); + c = c2.clone(); + BOOST_MESSAGE( "finished release/clone test" ); + + + a_key = get_next_key( a_key ); + c3.insert( a_key, new T ); + a_key = get_next_key( a_key ); + c3.insert( a_key, new T ); + + c.transfer( c3.begin(), c3 ); + c.transfer( c3.begin(), c3.end(), c3 ); + BOOST_CHECK( c3.empty() ); + BOOST_CHECK( !c.empty() ); + c3.transfer( c ); + BOOST_CHECK( !c3.empty() ); + BOOST_CHECK( c.empty() ); + BOOST_MESSAGE( "finished transfer test" ); + + BOOST_CHECK( !c3.empty() ); + c3.replace( c3.begin(), new T ); + BOOST_MESSAGE( "finished set/map interface test" ); + + // @todo: make macro with algorithms so that the right erase() is called. + // c.unique(); + // c.unique( std::not_equal_to() ); + // c.remove( T() ); + // c.remove_if( std::binder1st< std::equal_to >( T() ) ); + + sub_range sub; + sub_range csub; + + i = c.find( get_next_key( a_key ) ); + ci = c2.find( get_next_key( a_key ) ); + c2.count( get_next_key( a_key ) ); + i = c.lower_bound( get_next_key( a_key ) ); + ci = c2.lower_bound( get_next_key( a_key ) ); + i = c.upper_bound( get_next_key( a_key ) ); + ci = c2.upper_bound( get_next_key( a_key ) ); + sub = c.equal_range( get_next_key( a_key ) ); + csub = c2.equal_range( get_next_key( a_key ) ); + + try + { + c.at( get_next_key( a_key ) ); + } + catch( const bad_ptr_container_operation& ) + { } + + try + { + c2.at( get_next_key( a_key ) ); + } + catch( const bad_ptr_container_operation& ) + { } + + BOOST_MESSAGE( "finished algorithms interface test" ); + + typename C::iterator it = c.begin(), e = c.end(); + for( ; it != e; ++it ) + { + std::cout << "\n mapped value = " << *it << " key = " << i.key(); + } + + BOOST_MESSAGE( "finished iterator test" ); +} + + +#include + +using namespace std; + +void test_map() +{ + ptr_map_test< ptr_map, Base, Derived >(); + ptr_map_test< ptr_map, Value, Value >(); + ptr_map_test< ptr_map >, Base, Derived >(); + ptr_map_test< ptr_map >, Value, Value >(); + + ptr_map_test< ptr_multimap, Base, Derived >(); + ptr_map_test< ptr_multimap, Value, Value >(); + ptr_map_test< ptr_multimap >, Base, Derived >(); + ptr_map_test< ptr_multimap >, Value, Value >(); + + string joe = "joe"; + string brian = "brian"; + string kenny = "kenny"; + + ptr_map m; + m.insert( joe, new int( 4 ) ); + m.insert( brian, new int( 6 ) ); + BOOST_CHECK( m[ "foo" ] == 0 ); + m[ "bar" ] += 5; + BOOST_CHECK( m[ "bar" ] == 5 ); + m[ joe ] += 56; + m[ brian ] += 10; + + BOOST_CHECK_THROW( (m.insert(kenny, 0 )), bad_ptr_container_operation ); + BOOST_CHECK_THROW( (m.replace(m.begin(), 0 )), bad_ptr_container_operation ); + BOOST_CHECK_THROW( (m.at("not there")), bad_ptr_container_operation ); + + for( ptr_map::iterator i = m.begin(); + i != m.end(); ++i ) + { + if( is_null(i) ) + BOOST_CHECK( false ); + const string& ref = i.key(); + int& ref2 = *i; + ref2++; + } +} + +#include +using boost::unit_test::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite* test = BOOST_TEST_SUITE( "Smart Container Test Suite" ); + + test->add( BOOST_TEST_CASE( &test_map ) ); + + return test; +} + + + + + + + diff --git a/test/ptr_map_adapter.cpp b/test/ptr_map_adapter.cpp new file mode 100755 index 0000000..af4b5f1 --- /dev/null +++ b/test/ptr_map_adapter.cpp @@ -0,0 +1,58 @@ + +#include "concept_check_data.hpp" +#include +#include + +using namespace std; + +int test_main( int, char*[] ) +{ + typedef_test< ptr_map, Derived >(); + typedef_test< ptr_map, Value >(); + + associative_container_test< ptr_map, Base, Derived >(); + associative_container_test< ptr_map, Value, Value >(); + + typedef_test< ptr_multimap, Derived >(); + typedef_test< ptr_multimap, Value >(); + + associative_container_test< ptr_multimap, Base, Derived >(); + associative_container_test< ptr_multimap, Value, Value >(); + + string joe = "joe"; + string brian = "brian"; + + ptr_map m; + m.insert( joe, new int( 4 ) ); + m.insert( brian, new int( 6 ) ); + m[ joe ] += 56; + m[ brian ] += 10; + + try + { + m[ "hans" ] = 4; + } + catch( const bad_ptr_container_operation& ) + { } + + return 0; +} + + +#include + +using boost::unit_test_framework::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite* test = BOOST_TEST_SUITE( "Smart Container Test Suite" ); + + test->add( BOOST_TEST_CASE( &test_container_adapter ) ); + + return test; +} + + + + + diff --git a/test/ptr_set.cpp b/test/ptr_set.cpp new file mode 100755 index 0000000..3ee26f9 --- /dev/null +++ b/test/ptr_set.cpp @@ -0,0 +1,37 @@ + +#include "associative_test_data.hpp" +#include + +void test_set() +{ + + ptr_set_test< ptr_set, Base, Derived >(); + ptr_set_test< ptr_set, Value, Value >(); + + ptr_set_test< ptr_multiset, Base, Derived >(); + ptr_set_test< ptr_multiset, Value, Value >(); + + ptr_set set; + + BOOST_CHECK_THROW( set.insert( 0 ), bad_ptr_container_operation ); + set.insert( new int(0) ); + BOOST_CHECK_THROW( (set.replace(set.begin(), 0 )), bad_ptr_container_operation ); +} + +#include +using boost::unit_test::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite* test = BOOST_TEST_SUITE( "Smart Container Test Suite" ); + + test->add( BOOST_TEST_CASE( &test_set ) ); + + return test; +} + + + + + + diff --git a/test/ptr_unordered_map.cpp b/test/ptr_unordered_map.cpp new file mode 100755 index 0000000..191ec7a --- /dev/null +++ b/test/ptr_unordered_map.cpp @@ -0,0 +1,57 @@ + +#include "associative_test_data.hpp" +#include "concept_check_data.hpp" +#include +#include + +using namespace std; + +void test_unordered_map() +{ + typedef_test< ptr_map, Derived >(); + typedef_test< ptr_map, Value >(); + + associative_container_test< ptr_map, Base, Derived >(); + associative_container_test< ptr_map, Value, Value >(); + + typedef_test< ptr_multimap, Derived >(); + typedef_test< ptr_multimap, Value >(); + + associative_container_test< ptr_multimap, Base, Derived >(); + associative_container_test< ptr_multimap, Value, Value >(); + + string joe = "joe"; + string brian = "brian"; + + ptr_map m; + m.insert( joe, new int( 4 ) ); + m.insert( brian, new int( 6 ) ); + m[ joe ] += 56; + m[ brian ] += 10; + + try + { + m[ "hans" ] = 4; + } + catch( const bad_ptr_container_operation& ) + { } +} + + + +#include + +using boost::unit_test_framework::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite* test = BOOST_TEST_SUITE( "Smart Container Test Suite" ); + + test->add( BOOST_TEST_CASE( &test_unordered_map ) ); + + return test; +} + + + + diff --git a/test/ptr_unordered_set.cpp b/test/ptr_unordered_set.cpp new file mode 100755 index 0000000..c4b03e6 --- /dev/null +++ b/test/ptr_unordered_set.cpp @@ -0,0 +1,46 @@ + +#include "associative_test_data.hpp2 +#include "concept_check_data.hpp" +#include + +void test_unordered_set() +{ + typedef_test< ptr_set, Derived >(); + typedef_test< ptr_set, Value >(); + + associative_container_test< ptr_set, Base, Derived >(); + associative_container_test< ptr_set, Value, Value >(); + + typedef_test< ptr_multiset, Derived >(); + typedef_test< ptr_multiset, Value >(); + + associative_container_test< ptr_multiset, Base, Derived >(); + associative_container_test< ptr_multiset, Value, Value >(); + +/* + algo_test< ptr_vector, Value >(); + algo_test_polymorphic< ptr_vector, Derived >(); +*/ + //c.insert( T() ); + //c.insert( t ); + +} + + +#include + +using boost::unit_test_framework::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite* test = BOOST_TEST_SUITE( "Smart Container Test Suite" ); + + test->add( BOOST_TEST_CASE( &test_unordered_set ) ); + + return test; +} + + + + + diff --git a/test/ptr_vector.cpp b/test/ptr_vector.cpp new file mode 100755 index 0000000..0af3db2 --- /dev/null +++ b/test/ptr_vector.cpp @@ -0,0 +1,55 @@ + +#include "sequence_test_data.hpp" +#include "concept_check_data.hpp" +#include +#include + +void test_ptr_vector() +{ + reversible_container_test< ptr_vector, Base, Derived >(); + reversible_container_test< ptr_vector, Value, Value >(); + reversible_container_test< ptr_vector< nullable >, Base, Derived >(); + reversible_container_test< ptr_vector< nullable >, Value, Value >(); + + ptr_vector vec( 100u ); + BOOST_CHECK( vec.capacity() >= 100u ); + + BOOST_CHECK_THROW( vec.push_back(0), bad_ptr_container_operation ); + BOOST_CHECK_THROW( (vec.insert( vec.begin(), 0 )), bad_ptr_container_operation ); + BOOST_CHECK_THROW( vec.at( 42 ), bad_ptr_container_operation ); + vec.push_back( new int(0) ); + BOOST_CHECK_THROW( (vec.replace(10u, new int(0))), bad_ptr_container_operation ); + BOOST_CHECK_THROW( (vec.replace(0u, 0)), bad_ptr_container_operation ); + + assign::push_back( vec )( new int(2) ) + ( new int(4) ) + ( new int(6) ) + ( new int(8) ); + ptr_vector vec2; + assign::push_back( vec2 ) + ( new int(1) ) + ( new int(3) ) + ( new int(5) ) + ( new int(7) ); + BOOST_CHECK( vec < vec2 ); + BOOST_CHECK( vec != vec2 ); + BOOST_CHECK( !(vec == vec2 ) ); + BOOST_CHECK( vec2 > vec ); + +} + +#include +using boost::unit_test::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite* test = BOOST_TEST_SUITE( "Smart Container Test Suite" ); + + test->add( BOOST_TEST_CASE( &test_ptr_vector ) ); + + return test; +} + + + + diff --git a/test/ptr_vector_size.cpp b/test/ptr_vector_size.cpp new file mode 100755 index 0000000..2a7eb09 --- /dev/null +++ b/test/ptr_vector_size.cpp @@ -0,0 +1,15 @@ +#include + +template class +boost::ptr_vector; + +template class +boost::ptr_vector; + +template class +boost::ptr_vector; + +template class +boost::ptr_vector; + + diff --git a/test/sequence_point.cpp b/test/sequence_point.cpp new file mode 100755 index 0000000..0f8398e --- /dev/null +++ b/test/sequence_point.cpp @@ -0,0 +1,52 @@ +#include + + +struct Fun +{ + Fun() + { + std::cout << "fun" << std::endl; + } + + template< class T > + void operator()( T t ) + { + } + + template< class T > + Fun& operator,( T r ) + { + return *this; + } +}; + +template< class T > +Fun foo( T t ) +{ + return Fun(); +} + + + +struct one +{ + one() + { + std::cout <<"one" << std::endl; + } +}; + +struct two +{ + two() + { + std::cout <<"two" << std::endl; + } +}; + +int main() +{ + foo( one() )( two() ); + + Fun(),one(),two(),one(); +} diff --git a/test/sequence_test_data.hpp b/test/sequence_test_data.hpp new file mode 100755 index 0000000..ff6f7a0 --- /dev/null +++ b/test/sequence_test_data.hpp @@ -0,0 +1,118 @@ + +#include "test_data.hpp" +#include +#include +#include + +template< typename C, typename B, typename T > +void reversible_container_test(); + + +template< typename C, typename B, typename T > +void reversible_container_test() +{ + + BOOST_MESSAGE( "starting reversible container test" ); + enum { max_cnt = 10, size = 100 }; + C c; + BOOST_CHECK( c.size() == 0 ); + c.push_back( new T ); + BOOST_CHECK( c.size() == 1 ); + + const C c2( c.clone() ); + BOOST_CHECK( c2.size() == c.size() ); + + C c3( c.begin(), c.end() ); + BOOST_CHECK( c.size() == c3.size() ); + + c.assign( c3.begin(), c3.end() ); + BOOST_CHECK( c.size() == c3.size() ); + + //c.assign( size, T() ); + c.assign( c3 ); + //BOOST_CHECK( c.size() == size ); + BOOST_MESSAGE( "finished construction test" ); + + BOOST_DEDUCED_TYPENAME C::allocator_type alloc = c.get_allocator(); + BOOST_DEDUCED_TYPENAME C::iterator i = c.begin(); + BOOST_DEDUCED_TYPENAME C::const_iterator ci = c2.begin(); + BOOST_DEDUCED_TYPENAME C::iterator i2 = c.end(); + BOOST_DEDUCED_TYPENAME C::const_iterator ci2 = c2.begin(); + BOOST_DEDUCED_TYPENAME C::reverse_iterator ri = c.rbegin(); + BOOST_DEDUCED_TYPENAME C::const_reverse_iterator cri = c2.rbegin(); + BOOST_DEDUCED_TYPENAME C::reverse_iterator rv2 = c.rend(); + BOOST_DEDUCED_TYPENAME C::const_reverse_iterator cvr2 = c2.rend(); + + BOOST_DEDUCED_TYPENAME C::ptr_iterator ptr_i = c.ptr_begin(); + BOOST_DEDUCED_TYPENAME C::ptr_const_iterator ptr_ci = c2.ptr_begin(); + BOOST_DEDUCED_TYPENAME C::ptr_iterator ptr_i2 = c.ptr_end(); + BOOST_DEDUCED_TYPENAME C::ptr_const_iterator ptr_ci2 = c2.ptr_begin(); + BOOST_DEDUCED_TYPENAME C::ptr_reverse_iterator ptr_ri = c.ptr_rbegin(); + BOOST_DEDUCED_TYPENAME C::ptr_const_reverse_iterator ptr_cri = c2.ptr_rbegin(); + BOOST_DEDUCED_TYPENAME C::ptr_reverse_iterator ptr_rv2 = c.ptr_rend(); + BOOST_DEDUCED_TYPENAME C::ptr_const_reverse_iterator ptr_cvr2 = c2.ptr_rend(); + + BOOST_MESSAGE( "finished iterator test" ); + + BOOST_DEDUCED_TYPENAME C::size_type s = c.size(); + BOOST_DEDUCED_TYPENAME C::size_type s2 = c.max_size(); + //c.resize( size, T() ); + //BOOST_CHECK( c.size() == size ); + c.push_back( new T ); + bool b = c.empty(); + BOOST_CHECK( !c.empty() ); + b = is_null( c.begin() ); + BOOST_CHECK( b == false ); + BOOST_DEDUCED_TYPENAME C::reference r = c.front(); + BOOST_DEDUCED_TYPENAME C::const_reference cr = c2.front(); + BOOST_DEDUCED_TYPENAME C::reference r2 = c.back(); + BOOST_DEDUCED_TYPENAME C::const_reference cr2 = c2.back(); + BOOST_MESSAGE( "finished accessors test" ); + + c.push_back( new T ); + //c.push_back( T() ); + c.pop_back(); + c.insert( c.end(), new T ); + //c.insert( c.end(), T() ); + //c.insert( c.end(), size, T() ); + //c.insert( c.end(), make_iterator_range( c3 ) ); + // vs. + c.insert( c.end(), c3 ); + c3.insert( c3.end(), c.begin(), c.end() ); + c.erase( c.begin() ); + c3.erase( c3.begin(), c3.end() ); + BOOST_CHECK( c3.empty() ); + c.swap( c3 ); + BOOST_CHECK( !c3.empty() ); + c3.clear(); + BOOST_CHECK( c3.empty() ); + C c4; + c4.swap(c3); + swap(c4,c3); + BOOST_MESSAGE( "finished modifiers test" ); + + c.push_back( new T ); c.push_back( new T ); c.push_back( new T ); + typedef BOOST_DEDUCED_TYPENAME C::auto_type auto_type; + + auto_type ptr = c.release( c.begin() ); + std::auto_ptr ap = c.release(); + c = c2.clone(); + BOOST_CHECK( !c.empty() ); + auto_type ptr2 = c.replace(c.begin(), new T ); + BOOST_MESSAGE( "finished release/clone/replace test" ); + + c3.push_back( new T ); + c3.push_back( new T ); + c3.push_back( new T ); + c.transfer( c.begin(), c3.begin(), c3 ); + c.transfer( c.end(), c3.begin(), c3.end(), c3 ); + c.transfer( c.end(), boost::make_iterator_range( c3 ), c3 ); + BOOST_CHECK( c3.empty() ); + BOOST_CHECK( !c.empty() ); + c3.transfer( c3.begin(), c ); + BOOST_CHECK( !c3.empty() ); + BOOST_CHECK( c.empty() ); + BOOST_MESSAGE( "finished transfer test" ); + +} + diff --git a/test/simple_test.cpp b/test/simple_test.cpp new file mode 100755 index 0000000..8f540b6 --- /dev/null +++ b/test/simple_test.cpp @@ -0,0 +1,95 @@ +#include +#include +#include +#include + +using namespace std; + +// +// A simple polymorphic class +// +class Poly +{ + int i_; + static int cnt_; + +public: + Poly() : i_( cnt_++ ) { } + virtual ~Poly() { } + void foo() { doFoo(); } + +private: + virtual void doFoo() { ++i_; } + +public: + friend inline bool operator>( const Poly& l, const Poly r ) + { + return l.i_ > r.i_; + } +}; + +int Poly::cnt_ = 0; + +// +// Normally we need something like this to compare pointers to objects +// +template< typename T > +struct sptr_greater +{ + bool operator()( const boost::shared_ptr& l, const boost::shared_ptr& r ) const + { + return *l > *r; + } +}; + +// +// one doesn't need to introduce new names or live with long ones +// +typedef boost::shared_ptr PolyPtr; + + +void simple_test() +{ + enum { size = 2000 }; + typedef vector vector_t; + typedef boost::ptr_vector ptr_vector_t; + vector_t svec; + ptr_vector_t pvec; + + for( int i = 0; i < size; ++i ) + { + svec.push_back( PolyPtr( new Poly ) ); + pvec.push_back( new Poly ); // no extra syntax + } + + for( int i = 0; i < size; ++i ) + { + svec[i]->foo(); + pvec[i].foo(); // automatic indirection + svec[i] = PolyPtr( new Poly ); + pvec.replace( i, new Poly ); // direct pointer assignment not possible, original element is deleted + } + + for( vector_t::iterator i = svec.begin(); i != svec.end(); ++i ) + (*i)->foo(); + + for( ptr_vector_t::iterator i = pvec.begin(); i != pvec.end(); ++i ) + i->foo(); // automatic indirection +} + +#include +using boost::unit_test::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite* test = BOOST_TEST_SUITE( "Smart Container Test Suite" ); + + test->add( BOOST_TEST_CASE( &simple_test ) ); + + return test; +} + + + + + diff --git a/test/stack_example.cpp b/test/stack_example.cpp new file mode 100755 index 0000000..5344e49 --- /dev/null +++ b/test/stack_example.cpp @@ -0,0 +1,25 @@ +#include +#include +#include + +typedef std::stack< int*,boost::ptr_vector > stack_type; + +int main() +{ + stack_type s; + s.push( new int(1) ); + s.push( new int(2) ); + s.push( new int(3) ); + s.push( new int(4) ); + s.push( new int(5) ); + + // + // Won't work since stack uses cont::value_type in the interface. + // Hence will require special adapter...if only containers + // would use reference as return types and value_type as + // argument types + // + BOOST_ASSERT( s.top() == 5 ); + +} + diff --git a/test/test_data.hpp b/test/test_data.hpp new file mode 100755 index 0000000..60e78d8 --- /dev/null +++ b/test/test_data.hpp @@ -0,0 +1,201 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace boost; + +////////////////////////////////////////////////////////////////////////////// +// Test class 1: a class hierarchy +////////////////////////////////////////////////////////////////////////////// + +class Base +{ + Base( const Base& r ) : data1(r.data1), data2(r.data2), + data3(r.data3), data(r.data) + { } + + Base& operator=( const Base& ); + int data1, data2, data3; + string data; + +public: + + Base() : data1(1), data2(2), data3(rand()%256), + data(lexical_cast(rand())) {} + virtual ~Base() { /** write debug code here */ } + void print( ostream& out ) const { do_print( out); } + Base* clone() const { return do_clone(); } + void foo() { do_foo(); } + + virtual bool less_than( const Base& b ) const + { + return true; + } + + virtual bool equal( const Base& b ) const + { + return this == &b ; + } + + bool data_less_than( const Base& b ) const + { + return data1 == b.data1 && data2 == b.data2 && data3 < b.data3; + } + + bool data_less_than2( const Base& b ) const + { + return data_less_than(b) && data < b.data; + } + +private: + virtual void do_print( ostream& out ) const { }; + virtual Base* do_clone() const { return new Base( *this ); }; + virtual void do_foo() { }; +}; + + + +ostream& operator<<( ostream& out, Base& b ) +{ + b.print( out ); + return out; +} + + +// +// We rely on argument dependent lookup +// for this to be found +// +Base* new_clone( const Base& b ) +{ + return b.clone(); +} + + + +bool operator<( const Base& l, const Base& r ) +{ + return l.less_than( r ); +} + + + +bool operator>( const Base& l, const Base& r ) +{ + return !l.less_than( r ) && r.less_than( l ); +} + + + +bool operator==( const Base& l, const Base& r ) +{ + return l.equal( r ); +} + + + +bool operator!=( const Base& l, const Base& r ) +{ + return !l.equal( r ); +} + + + +class Derived : public Base +{ + int i_; + + virtual void do_print( ostream& out ) const + { + out << i_; + } + + + virtual Base* do_clone() const + { + return new Derived; + } + + virtual void do_foo() + { + ++i_; + } + +public: + Derived() : i_( rand() ) + { } + + virtual bool less_than( const Base& b ) const + { + const Derived& d = dynamic_cast( b ); + return i_ < d.i_; + } +}; + +////////////////////////////////////////////////////////////////////////////// +// Test class 2: a value class +////////////////////////////////////////////////////////////////////////////// + +class Value +{ + string s_; + +public: + + Value() : s_( boost::lexical_cast( rand() ) ) + {} + + ~Value() { /** debug code here */ } + + string name() const + { + return s_; + } +}; + + + +bool operator<( const Value& l, const Value& r ) +{ + return l.name() < r.name(); +} + + + +bool operator>( const Value& l, const Value& r ) +{ + return l.name() > r.name(); +} + + + +bool operator==( const Value& l, const Value& r ) +{ + return l.name() == r.name(); +} + + + +bool operator!=( const Value& l, const Value& r ) +{ + return l.name() != r.name(); +} + + + +ostream& operator<<( ostream& out, const Value& v ) +{ + return out << v.name() << " "; +} + + + diff --git a/test/tree_test.cpp b/test/tree_test.cpp new file mode 100755 index 0000000..319d3d6 --- /dev/null +++ b/test/tree_test.cpp @@ -0,0 +1,270 @@ + +#include "test_data.hpp" +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace boost; + +class node; + +class tree +{ + typedef ptr_vector nodes_t; + nodes_t nodes; + +protected: + void swap( tree& r ) + { nodes.swap( r.nodes ); } + +public: + typedef nodes_t::iterator iterator; + typedef nodes_t::const_iterator const_iterator; + +public: + void add_child( node* n ); + void remove( iterator n ); + void write_tree( ostream& os ) const; + size_t size() const; + node& child( size_t idx ); + const node& child( size_t idx ) const; + iterator child_begin(); + const_iterator child_begin() const; + iterator child_end(); + const_iterator child_end() const; + iterator find( const string& match ); +}; + + + +class node : noncopyable +{ + virtual size_t do_node_size() const = 0; + virtual string do_description() const = 0; + virtual void do_write_value( ostream& os ) const = 0; + +public: + virtual ~node() { } + size_t node_size() const { return do_node_size(); } + string description() const { return do_description(); } + void write_value( ostream& os ) const { do_write_value( os ); } +}; + + + +class inner_node : public node, public tree +{ + string name; + + virtual size_t do_node_size() const + { + return tree::size(); + } + + virtual string do_description() const + { + return lexical_cast( name ); + } + + virtual void do_write_value( ostream& os ) const + { + os << " inner node: " << name; + } + + void swap( inner_node& r ) + { + name.swap( r.name ); + tree::swap( r ); + } + +public: + inner_node() : name("inner node") + { } + + inner_node( const string& r ) : name(r) + { } + + inner_node* release() + { + inner_node* ptr( new inner_node ); + ptr->swap( *this ); + return ptr; + } +}; + + + +template< class T > +class leaf : public node +{ + T data; + + virtual size_t do_node_size() const + { + return 1; + } + + virtual string do_description() const + { + return lexical_cast( data ); + } + + virtual void do_write_value( ostream& os ) const + { + os << " leaf: " << data; + } + +public: + leaf() : data( T() ) + { } + + leaf( const T& r ) : data(r) + { } + + void set_data( const T& r ) + { data = r; } +}; + +///////////////////////////////////////////////////////////////////////// +// tree implementation +///////////////////////////////////////////////////////////////////////// + +inline void tree::add_child( node* n ) +{ + nodes.push_back( n ); +} + +inline void tree::remove( iterator n ) +{ + BOOST_ASSERT( n != nodes.end() ); + nodes.erase( n ); +} + +void tree::write_tree( ostream& os ) const +{ + for( const_iterator i = nodes.begin(), + e = nodes.end(); + i != e; ++i ) + { + i->write_value( os ); + if( const inner_node* p = dynamic_cast( &*i ) ) + p->write_tree( os ); + } +} + +size_t tree::size() const +{ + size_t res = 1; + + for( const_iterator i = nodes.begin(), + e = nodes.end(); + i != e; ++i ) + { + res += i->node_size(); + } + + return res; +} + +inline node& tree::child( size_t idx ) +{ + return nodes[idx]; +} + +inline const node& tree::child( size_t idx ) const +{ + return nodes[idx]; +} + +inline tree::iterator tree::child_begin() +{ + return nodes.begin(); +} + +inline tree::const_iterator tree::child_begin() const +{ + return nodes.begin(); +} + +inline tree::iterator tree::child_end() +{ + return nodes.end(); +} + +inline tree::const_iterator tree::child_end() const +{ + return nodes.end(); +} + +tree::iterator tree::find( const string& match ) +{ + for( iterator i = nodes.begin(), + e = nodes.end(); + i != e; ++i ) + { + if( i->description() == match ) + return i; + + if( inner_node* p = dynamic_cast( &*i ) ) + { + iterator j = p->find( match ); + if( j != p->child_end() ) + return j; + } + + } + + return child_end(); +} + +///////////////////////////////////////////////////////////////////////// +// test case +///////////////////////////////////////////////////////////////////////// + +void test_tree() +{ + tree root; + BOOST_CHECK_EQUAL( root.size(), 1u ); + inner_node node1( "node 1" ); + node1.add_child( new leaf( "leaf 1" ) ); + node1.add_child( new leaf( 42 ) ); + inner_node node2( "node 2" ); + node2.add_child( new leaf( 42.0f ) ); + node2.add_child( new leaf( "leaf 4" ) ); + + root.add_child( node1.release() ); + BOOST_CHECK_EQUAL( root.size(), 4u ); + root.add_child( node2.release() ); + root.add_child( new inner_node( "node 3" ) ); + BOOST_CHECK_EQUAL( root.size(), 8u ); + root.add_child( new leaf( "leaf 5" ) ); + BOOST_CHECK_EQUAL( root.size(), 9u ); + + root.write_tree( cout ); + tree::iterator a_leaf = root.find( "42" ); + BOOST_CHECK( a_leaf != root.child_end() ); + BOOST_CHECK_EQUAL( a_leaf->description(), "42" ); + leaf& the_leaf = dynamic_cast< leaf& >( *a_leaf ); + the_leaf.set_data( 2*42 ); + BOOST_CHECK_EQUAL( a_leaf->description(), "84" ); + +} + +#include +using boost::unit_test::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite* test = BOOST_TEST_SUITE( "Smart Container Test Suite" ); + + test->add( BOOST_TEST_CASE( &test_tree ) ); + + return test; +} + + diff --git a/test/tut1.cpp b/test/tut1.cpp new file mode 100755 index 0000000..8dd7ac8 --- /dev/null +++ b/test/tut1.cpp @@ -0,0 +1,342 @@ +// +// This example is intended to get you started. +// Notice how the smart container +// +// 1. takes ownership of objects +// 2. transfers ownership +// 3. applies indirection to iterators +// 4. clones objects from other smart containers +// + +// +// First we select which container to use. +// +#include + +// +// we need these later in the example +// +#include +#include +#include + + +// +// Then we define a small polymorphic class +// hierarchy. +// + +class animal : boost::noncopyable +{ + virtual std::string do_speak() const = 0; + std::string name_; + +protected: + // + // Animals cannot be copied... + // + animal( const animal& r ) : name_( r.name_ ) { } + void operator=( const animal& ); + +private: + // + // ...but due to advances in genetics, we can clone them! + // + + virtual animal* do_clone() const = 0; + +public: + animal( const std::string& name ) : name_(name) { } + virtual ~animal() throw() { } + + std::string speak() const + { + return do_speak(); + } + + std::string name() const + { + return name_; + } + + animal* clone() const + { + return do_clone(); + } +}; + +// +// An animal is still not Clonable. We need this last hook. +// +// Notice that we pass the animal by const reference +// and return by pointer. +// + +animal* new_clone( const animal& a ) +{ + return a.clone(); +} + +// +// We do not need to define 'delete_clone()' since +// since the default is to call the default 'operator delete()'. +// + +const std::string muuuh = "Muuuh!"; +const std::string oiink = "Oiiink"; + +class cow : public animal +{ + virtual std::string do_speak() const + { + return muuuh; + } + + virtual animal* do_clone() const + { + return new cow( *this ); + } + +public: + cow( const std::string& name ) : animal(name) { } +}; + +class pig : public animal +{ + virtual std::string do_speak() const + { + return oiink; + } + + virtual animal* do_clone() const + { + return new pig( *this ); + } + +public: + pig( const std::string& name ) : animal(name) { } +}; + +// +// Then we, of course, need a place to put all +// those animals. +// + +class farm +{ + // + // This is where the smart containers are handy + // + typedef boost::ptr_deque barn_type; + barn_type barn; + + // + // An error type + // + struct farm_trouble : public std::exception { }; + +public: + // + // We would like to make it possible to + // iterate over the animals in the farm + // + typedef barn_type::iterator animal_iterator; + + // + // We also need to count the farm's size... + // + typedef barn_type::size_type size_type; + + // + // And we also want to transfer an animal + // safely around. The easiest way to think + // about '::auto_type' is to imagine a simplified + // 'std::auto_ptr' ... this means you can expect + // + // T* operator->() + // T* release() + // deleting destructor + // + // but not more. + // + typedef barn_type::auto_type animal_transport; + + // + // Create an empty farm. + // + farm() { } + + // + // We need a constructor that can make a new + // farm by cloning a range of animals. + // + farm( animal_iterator begin, animal_iterator end ) + : + // + // Objects are always cloned before insertion + // unless we explicitly add a pointer or + // use 'release()'. Therefore we actually + // clone all animals in the range + // + barn( begin, end ) { } + + // + // ... so we need some other function too + // + + animal_iterator begin() + { + return barn.begin(); + } + + animal_iterator end() + { + return barn.end(); + } + + // + // Here it is quite ok to have an 'animal*' argument. + // The smart container will handle all ownership + // issues. + // + void buy_animal( animal* a ) + { + barn.push_back( a ); + } + + // + // The farm can also be in economical trouble and + // therefore be in the need to sell animals. + // + animal_transport sell_animal( animal_iterator to_sell ) + { + if( to_sell == end() ) + throw farm_trouble(); + + // + // Here we remove the animal from the barn, + // but the animal is not deleted yet...it's + // up to the buyer to decide what + // to do with it. + // + return barn.release( to_sell ); + } + + // + // How big a farm do we have? + // + size_type size() const + { + return barn.size(); + } + + // + // If things are bad, we might choose to sell all animals :-( + // + std::auto_ptr sell_farm() + { + return barn.release(); + } + + // + // However, if things are good, we might buy somebody + // else's farm :-) + // + + void buy_farm( std::auto_ptr other ) + { + // + // This line inserts all the animals from 'other' + // and is guaranteed either to succeed or to have no + // effect + // + barn.transfer( barn.end(), // insert new animals at the end + *other ); // we want to transfer all animals, + // so we use the whole container as argument + // + // You might think you would have to do + // + // other.release(); + // + // but '*other' is empty and can go out of scope as it wants + // + BOOST_ASSERT( other->empty() ); + } + +}; // class 'farm'. + +int main() +{ + // + // First we make a farm + // + farm animal_farm; + BOOST_ASSERT( animal_farm.size() == 0u ); + + animal_farm.buy_animal( new pig("Betty") ); + animal_farm.buy_animal( new pig("Benny") ); + animal_farm.buy_animal( new pig("Jeltzin") ); + animal_farm.buy_animal( new cow("Hanz") ); + animal_farm.buy_animal( new cow("Mary") ); + animal_farm.buy_animal( new cow("Frederik") ); + BOOST_ASSERT( animal_farm.size() == 6u ); + + // + // Then we make another farm...it will actually contain + // a clone of the other farm. + // + farm new_farm( animal_farm.begin(), animal_farm.end() ); + BOOST_ASSERT( new_farm.size() == 6u ); + + // + // Is it really clones in the new farm? + // + BOOST_ASSERT( new_farm.begin()->name() == "Betty" ); + + // + // Then we search for an animal, Mary (the Crown Princess of Denmark), + // because we would like to buy her ... + // + typedef farm::animal_iterator iterator; + iterator to_sell; + for( iterator i = animal_farm.begin(), + end = animal_farm.end(); + i != end; ++i ) + { + if( i->name() == "Mary" ) + { + to_sell = i; + break; + } + } + + farm::animal_transport mary = animal_farm.sell_animal( to_sell ); + + + if( mary->speak() == muuuh ) + // + // Great, Mary is a cow, and she may live longer + // + new_farm.buy_animal( mary.release() ); + else + // + // Then the animal would be destroyed (!) + // when we go out of scope. + // + ; + + // + // Now we can observe some changes to the two farms... + // + BOOST_ASSERT( animal_farm.size() == 5u ); + BOOST_ASSERT( new_farm.size() == 7u ); + + // + // The new farm has however underestimated how much + // it cost to feed Mary and its owner is forced to sell the farm... + // + animal_farm.buy_farm( new_farm.sell_farm() ); + + BOOST_ASSERT( new_farm.size() == 0u ); + BOOST_ASSERT( animal_farm.size() == 12u ); +} diff --git a/test/tut34.cpp b/test/tut34.cpp new file mode 100755 index 0000000..5e25480 --- /dev/null +++ b/test/tut34.cpp @@ -0,0 +1,50 @@ +#include +#include +#include +#include + +template< class T > +struct my_ptr_vector : + public boost::ptr_sequence_adapter< std::vector > +{ + +}; + + +template< class Key, class T, class Pred = std::less, + class Allocator = std::allocator< std::pair > > +struct my_map : public std::map +{ + explicit my_map( const Pred& pred = Pred(), + const Allocator& alloc = Allocator() ) + { } +}; + +#include +struct Foo {}; + +typedef boost::ptr_map_adapter< my_map > foo_map; + +template< class Key, class T, class Pred = std::less > +struct my_ptr_map : public boost::ptr_map_adapter< std::map > +{ + +}; + +typedef my_ptr_map foo_map2; + + +int main() +{ + + my_ptr_vector vec; + vec.push_back( new Foo ); + foo_map m1; + foo_map2 m2; + std::string s(""); + m1.insert( s, new Foo ); + m2.insert( s, new Foo ); + + +} + diff --git a/test/tut5.cpp b/test/tut5.cpp new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/test/tut5.cpp @@ -0,0 +1 @@ + diff --git a/test/vector_size.cpp b/test/vector_size.cpp new file mode 100755 index 0000000..d91175d --- /dev/null +++ b/test/vector_size.cpp @@ -0,0 +1,15 @@ +#include + +template class +std::vector; + +template class +std::vector; + +template class +std::vector; + +template class +std::vector; + + diff --git a/test/view_example.cpp b/test/view_example.cpp new file mode 100755 index 0000000..a78025e --- /dev/null +++ b/test/view_example.cpp @@ -0,0 +1,160 @@ +// +// This example is intended to show you how to +// use the 'view_clone_manager'. The idea +// is that we have a container of non-polymorphic +// objects and want to keep then sorted by different +// criteria at the same time. +// + +// +// We'll go for 'ptr_vector' here. Using a node-based +// container would be a waste of space here. +// All container headers will also include +// the Clone Managers. +// +#include +#include + +#include // For 'rand()' +#include // For 'std::sort()' +#include // For 'std::cout' + + +// +// This is our simple example data-structure. It can +// be ordered in three ways. +// +struct photon +{ + photon() : color( rand() ), + direction( rand() ), + power( rand() ) + { } + + int color; + int direction; + int power; +}; + +// +// Our big container is a standard vector +// +typedef std::vector vector_type; + +// +// Now we define our view type by adding a second template argument. +// The 'view_clone_manager' will implements Cloning by taking address +// of objects. +// +// Notice the first template argument is 'photon' and not +// 'const photon' to allow the view container write access. +// +typedef boost::ptr_vector view_type; + +// +// Our first sort criterium +// +struct sort_by_color +{ + bool operator()( const photon& l, const photon& r ) const + { + return l.color < r.color; + } +}; + +// +// Our second sort criterium +// +struct sort_by_direction +{ + bool operator()( const photon& l, const photon& r ) const + { + return l.direction < r.direction; + } +}; + + +// +// Our third sort criterium +// +struct sort_by_power +{ + bool operator()( const photon& l, const photon& r ) const + { + return l.power < r.power; + } +}; + +// +// This function inserts "Clones" into the +// the view. +// +// We need to pass the first argument +// as a non-const reference to be able to store +// 'T*' instead of 'const T*' objects. Alternatively, +// we might change the declaration of the 'view_type' +// to +// typedef boost::ptr_vector +// view_type; ^^^^^^ +// +void insert( vector_type& from, view_type& to ) +{ + to.insert( to.end(), + from.begin(), + from.end() ); +} + +int main() +{ + enum { sz = 10, count = 500 }; + + // + // First we create the main container and two views + // + std::vector photons; + view_type color_view; + view_type direction_view; + + // + // Then we fill the main container with some random data + // + for( int i = 0; i != sz; ++i ) + { + photons.push_back( vector_type() ); + + for( int j = 0; j != count; ++j ) + photons[i].push_back( photon() ); + } + + // + // Then we create the two views. + // + for( int i = 0; i != sz; ++i ) + { + insert( photons[i], color_view ); + insert( photons[i], direction_view ); + } + + // + // First we sort the original photons, using one of + // the view classes. This may sound trivial, but consider that + // the objects are scatered all around 'sz' different vectors; + // the view makes them act as one big vector. + // + // Notice how we simple use + // '.begin()/end()' instead of '.ptr_begin()/ptr_end()': + // + std::sort( color_view.begin(), color_view.end(), sort_by_power() ); + + // + // And now we can sort the views themselves. Notice how + // we switch to different iterators and different predicates: + // + std::sort( color_view.ptr_begin(), color_view.ptr_end(), + boost::indirected2() ); + + std::sort( direction_view.ptr_begin(), direction_view.ptr_end(), + boost::indirected2() ); + + return 0; +} diff --git a/test/xml_tree_test.cpp b/test/xml_tree_test.cpp new file mode 100755 index 0000000..8c03aba --- /dev/null +++ b/test/xml_tree_test.cpp @@ -0,0 +1,173 @@ + +#include "test_data.hpp" +#include +#include +#include +#include +#include +#include +#include +#include + +// +// This example uses an idiom that makes it possible to override functions in base classes without +// using virtual functions. Hence the name Non-Virtual Virtual Functions Idiom. The +// idiom has these tradeoffs: +// Pro: +// 1. fast +// 2. no vtable space overhead +// 3. allows "virtual" functions templates +// +// Con: +// 1. limited to one layer of derivation +// 2. no run-time type-switching possible +// 3. not very flexible +// +// We shall compare it with a traditional way of doing it that uses virtual functions and a container +// of smart-pointers. +// + +namespace slow +{ + class xml_node; + + class xml_tree + { + public: + typedef boost::shared_ptr< xml_node > node_ptr; + typedef std::vector< node_ptr > nodes_t; + + private: + nodes_t nodes; + + public: + void add( xml_node* n ); + void write_tree( ostream& os ) const; + size_t size() const; + }; + + + class xml_node + { + virtual size_t do_size() const = 0; + virtual string do_description() const = 0; + + public: + virtual ~xml_node() { } + size_t size() const { return do_size(); } + string description() const { return do_description(); } + }; + +} // namespace 'slow' + +namespace fast +{ + + class xml_node; + + class xml_tree + { + typedef boost::ptr_vector nodes_t; + nodes_t nodes; + + public: + + + public: + void add( xml_node* n ); + void write_tree( ostream& os ) const; + size_t size() const; + }; + + + enum derive_classes + { + simple, + complex + }; + + class xml_node_base + { + public: + + }; + + class xml_node + { + void* self_; // store pointer derived class + + xml_node(); + xml_node( const xml_node& ); + void operator=( const xml_node& ); + ~xml_node() // forward, substitute for virtual desructor + { + switch( derived_classes ) + { + case simple: delete (simple_node*)self_; break; + case complex: delete (complex_node*)self_; break; + default: BOOST_ASSERT( false ); + } + } + friend void ::operator delete( void* ); // only allow heap objects or references + public: + + xml_node( void* self ) : self_( self ) { } + size_t size() const { return self_->size(); } // forward + string description() const { return self_->description(); } // forward + }; + +} // namespace 'fast' + + +/* +template< class T > +class inner_node : public node, public tree +{ + T t_; + + virtual size_t do_size() const = 0; + virtual string do_description() const = 0; + virtual void do_write_value( ostream& os ) const = 0; + +public: + inner_node() + { + } +}; + + + +template< class T > +class leaf : public node +{ + T t_; + + virtual size_t do_size() const = 0; + virtual string do_description() const = 0; + virtual void do_write_value( ostream& os ) const = 0; +public: + leaf() + { + } +}; +*/ + +void test_tree() +{ +} + + + +#include +using boost::unit_test::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite* test = BOOST_TEST_SUITE( "Smart Container Test Suite" ); + + test->add( BOOST_TEST_CASE( &test_tree ) ); + + return test; +} + +