Newsgroup: it.comp.lang.c++
Titolo: STL: un piccolo aiuto...

Come si puo' fare per leggere un predeterminato numero di oggetti con la funzione
'copy' delle STL senza dover leggere fino ad EOF con:
copy(input_iterator<oggetto>(cin), input_iterator<oggetto>(), destination_iterator);
?
Ringrazio chi vorra' intervenire sull'argomento.
Claudio
--
******* Claudio Castelpietra *******
E-mail:  
i09...@spv.ing.uniroma1.it
 
castel...@acm.org
URL: 
http://spv22.ing.uniroma1.it:8080/clix.html

copy(input_iterator<oggetto>(cin), input_iterator<oggetto>(),
destination_iterator);
[NB: e` istream_iterator<> nella versione attuale, "input iterator" resta
solo
come nome generico...]
Non in modo banale, perche` un input iterator in generale non supporta un
"+ n" per indicare ``n posti piu` avanti''.  Se hai un forward iterator (e
"sai" che
devi leggere esattamente N oggetti, *mai* meno di N...) allora e` banale:
template <class InIt, class OutIt> inline
OutIt copy_n(InIt start, size_t n, OutIt dest) {
    return copy(start, start+n, dest);
}
tanto per dare massima generalita`.  Ma non funziona con
istream_iterator...!
Se ti trovi spesso con problemi come questi e` abbastanza facile definire
un "iterator adapter" -- un template che ti "arricchisce" un iterator dato
con
caratteristiche "migliorate" per i tuoi scopi... per farlo con piena
generalita`
ti serve una accoppiata compilatore/libreria aggiornata, e in particolare
una
che supporti appieno iterator_traits (o ti fornisca workaround
equivalenti...),
e il lavoro benche` non difficile e` noioso (il ctor deve accettare uno
start,
end, *e* conteggio massimo; il ++ deve decrementare il conteggio max
rimasto, e se si azzera settare start a end).  Piu` semplice se ti
interessa solo per istream_iterator, naturalmente (esempietto di
adapter, non testato ma penso che piu` o meno funzioni, salvo
eventuali off-by-one:-):
template<class U, class E = char, class T = char_traits<E> >
class counted_istream_iterator: public istream_iterator<U, E, T>
{
private:
    distance_type remaining;
public:
    typedef istream_iterator<U, E, T> base;
    counted_istream_iterator(): remaining(0) {}
    counted_istream_iterator(istream_type& is, distance_type count):
        istream_iterator(is), remaining(count) {}
    bool finished() const { return remaining==0; }
    counted_istream_iterator<U, E, T>& operator++() {
        if(finished()) {
            *this = counted_istream_iterator();
        } else {
            --remaining;
            base::operator++();
        }
        return *this;
    }
    counted_istream_iterator<U, E, T> operator++(int) {
        counted_istream_iterator<U, E, T> temp = *this;
        operator++();
        return temp;
    }
};
template<class T, class U, class E> inline
bool operator==(
        const counted_istream_iterator<T, U, E>& lhs,
        const counted_istream_iterator<T, U, E>& rhs)
{
    if(lhs.finished()) return rhs.finished();
    return operator==(static_cast< istream_iterator<T,U,E> >(lhs),
                    static_cast< istream_iterator<T,U,E> >(rhs));
}
Adesso...:
copy(counted_istream_iterator<o>(cin, imax),
    counted_istream_iterator<o>(), destination_iterator);
dovrebbe funzionare come richiesto.
Naturalmente, varra` la pena di fare un adapter solo se la
frequenza di uso lo merita, se no e` meglio sostituire
l'algoritmo copy() con uno piu` appropriato:-).
Alex