Boost logo

Boost :

From: Rémi Chateauneu (ravioli_at_[hidden])
Date: 2002-09-04 14:01:32


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
*******************************************************************/


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