Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2002-09-05 11:01:27


Rémi,

I didn't have time to look at your code in detail, but it has a rather
serious flaw: inheritance changes the type of the iterator so that various
functions no longer fulfill their requirements. For example, the result
type of ++x, where x is one of your "iterators", will be wrong.

-----------------------------------------------------------
           David Abrahams * Boost Consulting
dave_at_[hidden] * http://www.boost-consulting.com

----- Original Message -----
From: "Rémi Chateauneu" <ravioli_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Wednesday, September 04, 2002 3:01 PM
Subject: [boost] indirect_iterator_adaptor with output_iterator

> boost::indirect_iterator_adaptor is a flavor of iterator_adaptor,
> that allows to work with container of pointers on objects, exactly
> as they were container of objects (without indirection).
> But, it seems that for the moment, it works only with input_ietartor
> and random_access_iterator.
>
> With indirect_output_iterator_adaptor, you can as well have an output
> iterator
> pointing to a container of pointers to objects : This adaptor does the
> necessary allocation.
>
> Please see the implementation, followed by an exemple.
>
> /*******************************************************************
> ** indirect_output_iterator_adaptor.cpp
> *******************************************************************/
>
>
> #include <iostream>
> #include <list>
> #include <set>
> #include <vector>
> #include <assert.h>
>
> #include <iterator>
> #include <boost/iterator_adaptors.hpp>
>
> /*******************************************************************
> ** indirect_output_iterator_adaptor
> ** This template allows to use output_iterator (able to automatically
> ** inserts a new element at the right place) with indirect_iterators
(ie
> : iterator on containers
> ** where not the data, but a pointer on the data is stored).
> *******************************************************************/
> template < class OUTPUT_ITER, class TYPE >
> struct indirect_output_iterator_adaptor
> : public
> boost::iterator_adaptor<
> OUTPUT_ITER,
> boost::default_iterator_policies,
> TYPE,
> TYPE &,
> TYPE *,
> std::output_iterator_tag,
> std::size_t >
> {
> typedef
> boost::iterator_adaptor<
> OUTPUT_ITER,
> boost::default_iterator_policies,
> TYPE,
> TYPE &,
> TYPE *,
> std::output_iterator_tag,
> std::size_t >
> base_type ;
>
> indirect_output_iterator_adaptor( OUTPUT_ITER the_iter )
> : base_type( the_iter ) {};
>
> // Does basically the same as an output_iterator, i.e. inserts
> // the data, after it has been stored in a newly allocated pointer.
> indirect_output_iterator_adaptor &
> operator = ( const TYPE & the_obj ) {
> TYPE * my_ptr = new TYPE( the_obj );
> *base() = my_ptr ;
> return *this ;
> };
>
> // Same as std::output_iterator.
> indirect_output_iterator_adaptor & operator*() {
> return *this ;
> }
> }; // indirect_output_iterator_adaptor
>
> /*******************************************************************
> ** The rest is for testing only.
> *******************************************************************/
>
> // For testing the correctness of an insert_iterator to a set<>,
> // even qith an alternate compare function.
> template < class TYPE >
> struct ptr_cmp
> {
> bool operator()( const TYPE * the_a, const TYPE * the_b ) {
> return *the_a > *the_b ;
> };
> }; // ptr_cmp
>
> // Testing program doing various insertions with
indirect_output_iterators
> template< class TYPE >
> void main_test( TYPE * the_debut, TYPE * the_fin, TYPE the_extra )
> {
> std::size_t my_nb = std::distance( the_debut, the_fin );
> typedef std::list< TYPE * > list_t ;
> list_t my_list ;
>
> typedef std::set< TYPE *, ptr_cmp< TYPE > > set_t ;
>
> typedef
> indirect_output_iterator_adaptor< std::back_insert_iterator< list_t
>,
> TYPE >
> indirect_output_iterator_adaptor_list ;
>
> typedef
> indirect_output_iterator_adaptor< std::insert_iterator< set_t >,
TYPE >
> indirect_output_iterator_adaptor_set ;
>
> set_t my_set ;
>
> TYPE * * my_tab_ptr = new TYPE *[ my_nb ];
>
> std::copy(
> the_debut,
> the_fin,
> std::ostream_iterator< TYPE >( std::cout, "," ) );
> std::cout << std::endl ;
>
> for( TYPE * my_it = the_debut ; my_it != the_fin ; ++my_it ) {
> my_tab_ptr [ std::distance( the_debut, my_it ) ] = my_it ;
> my_list.push_back( my_it );
> my_set.insert( my_it );
> }
>
> boost::indirect_iterator_generator< TYPE **, TYPE >::type
> my_first( my_tab_ptr ), my_last( my_tab_ptr + my_nb );
> std::copy(
> my_first,
> my_last,
> std::ostream_iterator< TYPE >( std::cout, "," ) );
> std::cout << std::endl ;
>
> boost::indirect_iterator_generator< set_t::iterator, TYPE >::type
> my_first_s( my_set.begin() ), my_last_s( my_set.end() );
> std::copy(
> my_first_s,
> my_last_s,
> std::ostream_iterator< TYPE >( std::cout, "," ) );
> std::cout << std::endl ;
>
> boost::indirect_iterator_generator< list_t::iterator, TYPE >::type
> my_first_l( my_list.begin() ), my_last_l( my_list.end() );
> std::copy(
> my_first_l,
> my_last_l,
> std::ostream_iterator< TYPE >( std::cout, "," ) );
> std::cout << std::endl ;
>
>
> if( ! std::equal(
> the_debut,
> the_fin,
> my_first /* boost::make_indirect_iterator( my_tab_ptr ) */ ) )
{
> std::cout << "Erreur comparaison" << std::endl ;
> return ;
> }
>
> indirect_output_iterator_adaptor_list
> _out( std::back_inserter( my_list ) ) ;
> my_out++ ;
> *my_out = the_extra ;
>
> indirect_output_iterator_adaptor_set my_out_s( std::inserter(
my_set,
> my_set.end() ) ) ;
> my_out_s++ ;
> *my_out_s = the_extra ;
>
> std::copy(
> the_debut,
> the_fin,
> my_out );
>
> std::cout << "List : Size = " << my_list.size() << std::endl ;
> boost::indirect_iterator_generator< list_t::iterator, TYPE >::type
> my_first_l2( my_list.begin() ), my_last_l2( my_list.end() );
> std::copy(
> my_first_l2,
> my_last_l2,
> std::ostream_iterator< TYPE >( std::cout, "," ) );
> std::cout << std::endl ;
>
> std::copy(
> the_debut,
> the_fin,
> my_out_s );
>
> std::cout << "Set : Size = " << my_set.size() << std::endl ;
> boost::indirect_iterator_generator< set_t::iterator, TYPE >::type
> my_first_s2( my_set.begin() ), my_last_s2( my_set.end() );
> std::copy(
> my_first_s2,
> my_last_s2,
> std::ostream_iterator< TYPE >( std::cout, "," ) );
> std::cout << std::endl ;
>
> delete[] my_tab_ptr ;
> return ;
> }; // main
>
> struct Char {
> char m_char ;
> Char() {};
> Char( const Char & the_char ) : m_char( the_char.m_char ) {};
> Char( char the_char ) : m_char( the_char ) {};
> bool operator == ( const Char & the_char ) const {
> return m_char == the_char.m_char ;
> };
> bool operator > ( const Char & the_char ) const {
> return m_char < the_char.m_char ;
> };
>
> friend std::ostream & operator << ( std::ostream & the_o, const Char
&
> the_c )
> {
> the_o << the_c.m_char ;
> return the_o ;
> }
> };
>
> // The main test calling function; which calls main_test
> // with various data types.
> void ptr_test(void)
> {
> #define SZ 5
> static int my_tab[SZ] = { 33, 22, 11, 55, 44 };
>
> main_test< int >( my_tab, my_tab + SZ, 999999 );
>
> char * my_str = "troulala" ;
> main_test( my_str, my_str + strlen(my_str), 'Z' );
>
> std::vector< Char > my_Char ;
> my_Char.push_back( 't' );
> my_Char.push_back( 'r' );
> my_Char.push_back( 'o' );
> my_Char.push_back( 'u' );
> my_Char.push_back( 'l' );
> my_Char.push_back( 'a' );
> my_Char.push_back( 'l' );
> my_Char.push_back( 'a' );
> main_test( my_Char.begin(), my_Char.end(), Char('Z') );
> }; // ptr_test
>
> /*******************************************************************
> ** indirect_output_iterator_adaptor.cpp
> *******************************************************************/
>
>
>
>
>
> _______________________________________________
> Unsubscribe & other changes:
http://lists.boost.org/mailman/listinfo.cgi/boost


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk