Search code examples
c++iteratorstl-algorithmistream-iterator

How to read arbitrary number of values using std::copy?


I'm trying to code opposite action to this:

std::ostream outs; // properly initialized of course
std::set<int> my_set; // ditto

outs << my_set.size();
std::copy( my_set.begin(), my_set.end(), std::ostream_iterator<int>( outs ) );

it should be something like this:

std::istream ins;

std::set<int>::size_type size;
ins >> size;

std::copy( std::istream_iterator<int>( ins ), std::istream_iterator<int>( ins ) ???, std::inserter( my_set, my_set.end() ) );

But I'm stuck with the 'end' iterator -- input interators can't use std::advance and neither I can use two streams with the same source...

Is there any elegant way how to solve this? Of course I can use for loop, but maybe there's something nicer :)


Solution

  • You could derive from the istream_iterator<T>.
    Though using Daemin generator method is another option, though I would generate directly into the set rather than use an intermediate vector.

    #include <set>
    #include <iterator>
    #include <algorithm>
    #include <iostream>
    
    
    template<typename T>
    struct CountIter: public std::istream_iterator<T>
    {
        CountIter(size_t c)
            :std::istream_iterator<T>()
            ,count(c)
        {}
        CountIter(std::istream& str)
            :std::istream_iterator<T>(str)
            ,count(0)
        {}
    
        bool operator!=(CountIter const& rhs) const
        {
            return (count != rhs.count) && (dynamic_cast<std::istream_iterator<T> const&>(*this) != rhs);
        }
        T operator*()
        {
            ++count;
            return std::istream_iterator<T>::operator*();
        }
    
        private:
            size_t  count;
    };
    
    int main()
    {
        std::set<int>       x;
    
        //std::copy(std::istream_iterator<int>(std::cin),std::istream_iterator<int>(),std::inserter(x,x.end()));
        std::copy(
                    CountIter<int>(std::cin),
                    CountIter<int>(5),
                    std::inserter(x,x.end())
                );
    }