- #include <cassert> 
-   
- #include <algorithm> 
- #include <iostream> 
- #include <iterator> 
- #include <sstream> 
- #include <string> 
-   
-     class LineIterator: public std::iterator<std::input_iterator_tag, 
-                                              std::string const> 
-     { 
-     public: 
-         // Default Constructible 
-         LineIterator(): stream(nullptr) {} 
-   
-         explicit LineIterator(std::istream& is): stream(&is) { this->advance(); } 
-   
-         // Equality Comparable 
-         friend bool operator==(LineIterator const& left, LineIterator const& right) { 
-             return left.stream == right.stream 
-                and left.buffer == right.buffer 
-                and left.currentLine == right.currentLine; 
-         } 
-   
-         friend bool operator!=(LineIterator const& left, LineIterator const& right) { 
-             return not (left == right); 
-         } 
-   
-         // Trivial Iterator (non mutable) 
-         pointer operator->() const { return ¤tLine; } 
-   
-         reference operator*() const { return currentLine; } 
-   
-         // Input Iterator 
-         LineIterator& operator++() { 
-             this->advance(); 
-             return *this; 
-         } // operator++ 
-   
-         LineIterator operator++(int) { 
-             LineIterator tmp(*this); 
-             ++*this; 
-             return tmp; 
-         } // operator++ 
-   
-     private: 
-         void advance() { 
-             // Advance a valid iterator to fetch the next line from the source stream. 
-             static LineIterator const SingularValue; 
-   
-             assert(*this != SingularValue and "Cannot advance singular iterator"); 
-             // Note: in real life, I would use std::getline... 
-             // ... but it would not showcase the double-buffering model 
-             // required to solve the OP problem (because of decoding) 
-   
-             // We use double-buffering, so clear current and swap buffers 
-             currentLine.clear(); 
-             swap(buffer, currentLine); 
-   
-             // Check if we found some new line or not 
-             size_t const nl = currentLine.find('\n'); 
-   
-             // If we found one already, preserve what's after in the buffer 
-             // as we only want to expose one line worth of material. 
-             if (nl != std::string::npos) { 
-             	if (nl == currentLine.size()) { return; } // nothing to preserve 
-   
-                 buffer.assign(currentLine.begin() + nl + 1, currentLine.end()); 
-                 currentLine.erase(currentLine.begin() + nl + 1, currentLine.end()); 
-                 return; 
-             } 
-   
-             // If we did not, then we need to pump more data into the buffer. 
-             if (not stream) { return; } // Nothing to pump... 
-   
-             static size_t const ReadBufferSize = 256; 
-             char input[ReadBufferSize]; 
-   
-             while (stream->read(input, ReadBufferSize)) { 
-                 if (this->splitBuffer(input, ReadBufferSize)) { break; } 
-             } 
-   
-             // We end up here either if we found a new line or if some read failed. 
-             // If the stream is still good, we successfully found a new line! 
-             if (*stream) { return; } 
-   
-             // Otherwise, the stream is no good any longer (it dried up!) 
-             // but we may still have read some little things from it. 
-             this->splitBuffer(input, stream->gcount()); 
-   
-             stream = SingularValue.stream; // stream dried up, 
-                                            // so reset it to match singular value. 
-         } // advance 
-   
-         bool splitBuffer(char const* input, size_t const size) { 
-             // Split input at the newline character, the first chunk ends 
-             // up in currentLine, the second chunk in buffer. 
-             // Returns true if a newline character was found, false otherwise. 
-   
-             // Check if we finally found a new line 
-             char const* const newLine = std::find(input, input + size, '\n'); 
-   
-             // If we did not, copy everything into currentLine and signal it. 
-             if (newLine == input + size) { 
-                 currentLine.append(input, size); 
-                 return false; 
-             } 
-   
-             // If we did, copy everything up to it (including it) into currentLine 
-             // and then bufferize the rest for the next iteration. 
-             currentLine.append(input, newLine + 1); 
-             buffer.assign(newLine + 1, input + size); 
-             return true; 
-         } // splitBuffer 
-   
-         std::istream* stream; 
-         std::string buffer; 
-   
-         std::string currentLine; 
-     }; // class LineIterator 
-   
-   
- int main() { 
- 	std::stringstream ss; 
- 	ss << "Some string\nwith a couple\n\nnew lines\nthrown in"; 
-   
- 	std::cout << "$"; 
- 	std::copy(LineIterator(ss), 
- 	          LineIterator(), 
- 	          std::ostream_iterator<std::string>(std::cout, "$")); 
- 	return 0; 
- }