Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Limiting the range for std::copy with std::istream_iterator

I have constructed a minimal working example to show a problem I've encountered using STL iterators. I'm using istream_iterator to read floatss (or other types) from a std::istream:

#include <iostream> #include <iterator> #include <algorithm>  int main() {    float values[4];    std::copy(std::istream_iterator<float>(std::cin), std::istream_iterator<float>(), values);    std::cout << "Read exactly 4 floats" << std::endl; // Not true! } 

This reads all possible floatss, until EOF into values, which is of fixed size, 4, so now clearly I want to limit the range to avoid overflows and read exactly/at most 4 values.

With more "normal" iterators (i.e. RandomAccessIterator), provided begin+4 isn't past the end you'd do:

std::copy(begin, begin+4, out); 

To read exactly 4 elements.

How does one do this with std::istream_iterator? The obvious idea is to change the call to std::copy to be:

std::copy(std::istream_iterator<float>(std::cin), std::istream_iterator<float>(std::cin)+4, values); 

But (fairly predictably) this doesn't compile, there are no candidates for operator+:

g++ -Wall -Wextra test.cc test.cc: In function ‘int main()’: test.cc:7: error: no match for ‘operator+’ in ‘std::istream_iterator<float, char, std::char_traits<char>, long int>(((std::basic_istream<char, std::char_traits<char> >&)(& std::cin))) + 4’ 

Any suggestions? Is there a correct, "STLified" pre-C++0x way to achieve this? Obviously I could just write it out as a for loop, but I'm looking to learn something about the STL here. I half wondered about abusing std::transform or std::merge etc. to achieve this functionality somehow, but I can't quite see how to do it.

like image 989
Flexo Avatar asked May 10 '11 17:05

Flexo


1 Answers

Take a look at std::copy_n 

like image 120
Igor Nazarenko Avatar answered Sep 21 '22 23:09

Igor Nazarenko