Topic: STL extension: intervals
Author: "Sektor van Skijlen" <sektor@spam-buffer.aldec.com>
Date: Fri, 11 Jan 2002 13:07:36 CST Raw View
"Michiel Salters" <Michiel.Salters@cmg.nl> wrote in message
news:D%c%7.11353$cD4.24144@www.newsranger.com...
> Making this much public is a bad idea. In hindsight, even std::pair has too
> much public data. For instance, istreamiterators need a special singular
> iterator to signal EOF. Custom iterators wrapping existing APIs often have
> similar issues. This problem could be eased if an interval has a method
> bool atend( Iterator I );
> Leave it to the implementation of istreaminterval::atend() to determine
> how EOF is detected.
I think you have misunderstood. The interval class is not
intended for getting a begin and end from any container.
It serves to create a "virtual container" from just a
range of two iterators. It is helpful to create some
algorithms, which will take as an argument a full container
rather than two iterators; in this case you can create
an interval (using iv) and use it as it was just a container.
The algorithm then can use a container as a generalized
range (container, not interval).
Of course, there is possible to use it so:
interval<istream_iterator<int> > range( istream_iterator<int>( cin ),
istream_iterator<int>() );
There is no matter, how this iterator signifying EOF is used.
Its constructor is called when it's PASSED into the algorithm,
rather then it's checked for equality with the current iterator
inside the algorithm's code.
--
Regards,
((
)) ektor
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Sektor van Skijlen" <sektor@spam-buffer.aldec.com>
Date: Wed, 9 Jan 2002 15:54:31 CST Raw View
Interval is a derivative of pair of two iterators, which comprise
a begin and an end of the range.
Advanteges:
- there is a possibility to avoid passing both begin and end
for algorithms, which shall operate on the container. For example,
this can operate on full container:
for_each( list1, do_something );
where list1 must be a forward container. This forward container
can be created also from two iterators:
list<X>::iterator i1, i2;
... (find appropriate iterator values for i1 and i2 )
Then instead of now the standard:
for_each( i1, i2, do_something );
You use:
for_each( iv( i1, i2 ), do_something );
where 'iv' is a helper function which creates an interval. This interval
is just a pair of two iterators with begin() and end() in addition.
An additional feature is an integer iterator. This fakes a container of
subsequent integer numbers with appropriate step from appropriate
range. For example:
for_each( ivi( 0, 10 ), do_something );
will call do_something functor, passing subsequent numbers from 0 until 9
into its operator(). There are ivi (with step=1), ivd( with step=-1) and
ivs<step> helper functions to create an interval.
Here is the trial implementation of the interval and integer_iterator. Here,
interval contains also some algorithms as methods for more comfortable
use.
namespace std {
template <class It, int tSt = 1>
class interval: public pair<It,It>
{
public:
interval( const It& beg, const It& ned )
: pair<It,It>( beg, ned )
{ }
template <class Container>
interval( Container& c ): pair<It,It>( c.begin(), c.end() ) { }
// Container concept
It begin() const { return first; }
It end() const { return second; }
// Pay attention: the `size' method for interval uses `distance', which is
// linear time for forward and bidirectional container. You should NOT use
// interval::size() for other iterators. Instead, use Container::size.
size_t size() const { return distance( first, second ); }
template <class Pred> Pred apply( Pred pred )
{ return ::for_each( begin(), end(), pred ); }
// Use this algorithm instead of `apply', if given functional could
// cause iterator invalidation (e.g. delete a node).
template <class Pred> Pred apply_safe( Pred pred )
{
for ( It start, next = first; start != second; start = next ) {
start = next;
++next;
fn( *start );
}
return fn;
}
// Extension: a = op( a ) -> do_op( a )
template <class Op>
It trans( Op op )
{ return ::transform( begin(), end(), begin(), op ); }
template <class Out, class Op>
Out trans( Out to, Op op )
{ return ::transform( begin(), end(), to, op ); }
template <class In, class Out, class Op>
Out trans( In with, Out to, Op op )
{ return ::transform( begin(), end(), with, to, op ); }
template<class tT> It find( const tT& val ) const
{ return ::find( begin(), end(), val ); }
template <class Pred> It find_if( Pred pred ) const
{ return ::find_if( begin(), end(), pred ); }
template<class tT> typename iterator_traits<It>::difference_type
count( const tT& val ) const
{ return ::count( begin(), end(), val ); }
template <class Pred> typename iterator_traits<It>::difference_type
count_if( Pred pred ) const
{ return ::count_if( begin(), end(), pred ); }
template <class Out> Out copy( Out dest ) const
{ return ::copy( begin(), end(), dest ); }
template <class Out> Out rcopy( Out dest ) const
{ return ::copy_backward( begin(), end(), dest ); }
template <class Container> It search( Container& c ) const
{ return ::search( begin(), end(), c.begin(), c.end() ); }
template <class Cont, class Pred> It search( Cont& c, Pred p ) const
{ return ::search( begin(), end(), c.begin(), c.end(), p ); }
template <class Container>
It firstof( Container& c )
{ return ::find_first_of( begin(), end(), c.begin(), c.end() ); }
template <class Container, class Pred>
It firstof( Container& c, Pred pred )
{ return ::find_first_of( begin(), end(), c.begin(), c.end(), pred ); }
template <class Container>
It rsearch( Container& c )
{ return ::find_end( begin(), end(), c.begin(), c.end() ); }
template <class Container, class Pred>
It rsearch( Container& c, Pred pred )
{ return ::find_end( begin(), end(), c.begin(), c.end(), pred ); }
interval& sort() { return ::sort( begin(), end() ); }
template <class Pred>
interval& sort( Pred pred ) { return ::sort( begin(), end(), pred ); }
interval& msort() { return ::stable_sort( begin(), end() ); }
template <class Pred>
interval& msort( Pred pred )
{ return ::stable_sort( begin(), end(), pred ); }
template <class value_type>
value_type acm( value_type init )
{ return ::accumulate( begin(), end(), init ); }
template <class value_type, class Pred>
value_type acm( value_type init, Pred pred )
{ return ::accumulate( begin(), end(), init, pred ); }
};
template <class Iterator>
interval<Iterator, 1> iv( Iterator from, Iterator to )
{ return interval<Iterator, 1>( from, to ); }
template <class Container>
interval<typename Container::iterator, 1> all( Container& c )
{ return interval<typename Container::iterator, 1>( c ); }
template <class Tp, size_t size>
interval<Tp*> alltab( Tp (&tabref)[size] )
{
return interval<Tp*, 1>( static_cast<Tp*>( tabref ), tabref + size );
}
template <int tStep>
class integer_iterator: public random_access_iterator<int, int>
{
int current;
public:
integer_iterator( int h ): current( h ) {}
integer_iterator& operator++()
{ current += tStep; return *this; }
integer_iterator operator++( int )
{ integer_iterator temp = *this; ++*this; return temp; }
bool operator==( const integer_iterator& s ) const
{ return current == s.current; }
bool operator<( const integer_iterator& s ) const
{ return current < s.current; }
bool operator>( const integer_iterator& s ) const
{ return current > s.current; }
integer_iterator operator+( const integer_iterator& op )
{ return integer_iterator( current + op.current ); }
int operator*() { return current; }
};
template<>
size_t interval<integer_iterator<1>, 1>::size() const
{ return *begin() - *end() - 1; }
template<>
size_t interval<integer_iterator<-1>, -1>::size() const
{ return *end() - *begin() - 1; }
template<>
integer_iterator<1>& integer_iterator<1>::operator++()
{ ++current; return *this; }
template<>
integer_iterator<-1>& integer_iterator<-1>::operator++()
{ --current; return *this; }
interval<integer_iterator<1>, 1> ivi( int from, int to )
{ return interval<integer_iterator<1>, 1>( from, to ); }
interval<integer_iterator<-1>, -1> ivd( int from, int to )
{ return interval<integer_iterator<-1>, -1>( from, to ); }
template<int step>
interval<integer_iterator<step>, step> ivs( int from, int to )
{ return interval<integer_iterator<step>, step>( from, to ); }
}//namespace
Regardz
--
((
)) ektor
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Michiel Salters<Michiel.Salters@cmg.nl>
Date: Thu, 10 Jan 2002 18:40:05 GMT Raw View
In article <a1i6dq$5kk$1@news.tpi.pl>, Sektor van Skijlen says...
>
>Interval is a derivative of pair of two iterators, which comprise
>a begin and an end of the range.
>
>Advanteges:
> - there is a possibility to avoid passing both begin and end
>for algorithms, which shall operate on the container. For example,
>this can operate on full container:
>
>for_each( list1, do_something );
>
>where list1 must be a forward container. This forward container
>can be created also from two iterators:
>
>list<X>::iterator i1, i2;
>
>... (find appropriate iterator values for i1 and i2 )
>
>Then instead of now the standard:
>
>for_each( i1, i2, do_something );
>
>You use:
>
>for_each( iv( i1, i2 ), do_something );
>
>where 'iv' is a helper function which creates an interval. This interval
>is just a pair of two iterators with begin() and end() in addition.
[ implementation snipped ]
Making this much public is a bad idea. In hindsight, even std::pair has too
much public data. For instance, istreamiterators need a special singular
iterator to signal EOF. Custom iterators wrapping existing APIs often have
similar issues. This problem could be eased if an interval has a method
bool atend( Iterator I );
Leave it to the implementation of istreaminterval::atend() to determine
how EOF is detected.
--
Michiel Salters
Consultant Technical Software Engineering
CMG Trade, Transport & Industry
Michiel.Salters@cmg.nl
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]