Re: problem storing different iterators in a container
Lutz Altmann wrote:
Hi there :)
I'm trying to write a functor-class, which supports the de-
multiplexing of data from one
input-container to two or multiple output containers (de-
interleaving).
For example:
vec1 = [1 5 2 6 3 7]
#demultiplex vec1 -> result1,result2
result1 = [1 2 3]
result2 = [5 6 7]
The idea is, to provide a functor-class , which makes the de-
multiplexing very easy to use:
It should be possible to do soemthing like this:
snip<
DemuxFunctor func;
func.addChannel(output_iter);
func.addChannel(output_iter2);
..
..
for_each(input_vec.begin(),input_vec.end(),func);
snip<
It should be possible to "register" iterators to which the functor
writes the output-data.
here is my draft :
#include <vector>
#include <iterator>
using namespace std;
template<typename T>
class DemuxFunctor : public unary_function<void,T>
{
public:
DemuxFunctor():m_current(0){}
void operator()(const T& arg)
{
// add arg to one of the iterators
*(m_outchannels(m_current)) = arg;
// step ahead
(m_outchannels(m_current))++;
if (m_current >= m_outchannels.size())
{
m_current = 0;
}
else
{
m_current++;
}
}
template<typename X>
void addChannel(insert_iterator<X>& iter)
{
m_outchannels.push_back(iter);
}
private:
// PROBLEM : how to declare this vector !!!
vector<insert_iterator&> m_outchannels;..
unsigned int m_current;
};
The Problem is, that i have to save the (registered) iterators in a
data-structure - but because
different kinds of iterators (vectors,lists..) should be possible i
dont know how to declare the
iterator-vector .. is there a solution?!
Maybe you also have some princible comments to the design.
How about duck-typing. The following AbstractOutputIterator<> template might
be a type that use can use.
#include <algorithm>
using std::swap;
template < typename ValueType >
class AbstractOutputIterator {
struct base {
virtual
~base ( void ) {}
virtual
base * clone ( void ) = 0;
virtual
base & operator= ( ValueType const & rhs ) = 0;
virtual
void inc ( void ) = 0;
};
template < typename Iterator >
struct derived : public base {
Iterator the_iter;
derived ( Iterator iter )
: the_iter ( iter )
{}
~derived ( void ) {}
derived * clone ( void ) {
return ( new derived ( the_iter ) );
}
derived & operator= ( ValueType const & rhs ) {
the_iter = rhs;
return ( *this );
}
void inc ( void ) {
++ the_iter;
}
};
base * data_ptr;
public:
AbstractOutputIterator ( void )
: data_ptr ( 0 )
{}
template < typename Iterator >
AbstractOutputIterator ( Iterator iter )
: data_ptr ( new derived< Iterator > ( iter ) )
{}
AbstractOutputIterator ( AbstractOutputIterator const & other )
: data_ptr ( other.data_ptr ? other.data_ptr->clone() : 0 )
{}
AbstractOutputIterator & operator= ( AbstractOutputIterator rhs ) {
swap( *this, rhs );
return ( *this );
}
~AbstractOutputIterator ( void ) {
delete ( data_ptr );
}
friend
void swap ( AbstractOutputIterator & lhs, AbstractOutputIterator& rhs )
{
swap( lhs.data_ptr, rhs.data_ptr );
}
base & operator* ( void ) {
return ( *data_ptr );
}
AbstractOutputIterator & operator++ ( void ) {
data_ptr->inc();
return ( *this );
}
AbstractOutputIterator operator++ ( int ) {
AbstractOutputIterator result ( *this );
data_ptr->inc();
return ( result );
}
}; // AbstractOutputIterator
#include <vector>
#include <deque>
#include <list>
#include <iterator>
#include <algorithm>
int main ( void ) {
std::vector< int > iv;
std::deque< int > id;
std::list< int > il;
std::vector< AbstractOutputIterator<int> > iter;
iter.push_back( AbstractOutputIterator<int>
( std::back_inserter( iv ) ) );
iter.push_back( AbstractOutputIterator<int>
( std::back_inserter( id ) ) );
iter.push_back( AbstractOutputIterator<int>
( std::back_inserter( il ) ) );
* (iter[0]) ++ = 1;
* (iter[1]) ++ = 1;
* (iter[2]) ++ = 1;
* (iter[0]) ++ = 2;
* (iter[1]) ++ = 2;
* (iter[0]) ++ = 3;
std::copy( iv.begin(), iv.end(),
std::ostream_iterator<int>( std::cout, " " ) );
std::cout << '\n';
std::copy( id.begin(), id.end(),
std::ostream_iterator<int>( std::cout, " " ) );
std::cout << '\n';
std::copy( il.begin(), il.end(),
std::ostream_iterator<int>( std::cout, " " ) );
std::cout << '\n';
}
Note: the code is just a rough idea and has not been properly tested.
Best
Kai-Uwe Bux