You should avoid the issue. Just don't parse it all from the same stream if it isn't the same stream.
Low-Tech
A low-tech "solution" is to copy the stream to a stringstream, putting your "prefix" in the buffer first:
Live On Coliru
#include <iostream>
#include <string>
#include <sstream>
void print(std::istream &in) { // function not to be modified
std::string str;
while (in >> str)
std::cout << str << std::endl;
}
int main() {
std::string header = "hello ";
std::stringstream in;
in << header << std::cin.rdbuf();
print(in);
}
Given the input foo bar qux
prints:
hello
foo
bar
qux
High-Tech
You can always create a custom stream buffer that implements the behaviour you desire:
Live On Coliru
#include <iostream>
#include <sstream>
#include <vector>
template <typename B1, typename B2>
class cat_streambuf : public std::streambuf {
B1* _sb1;
B2* _sb2;
std::vector<char> _buf;
bool _insb1 = true;
public:
cat_streambuf(B1* sb1, B2* sb2) : _sb1(sb1), _sb2(sb2), _buf(1024) {}
int underflow() {
if (gptr() == egptr()) {
auto size = [this] {
if (_insb1) {
if (auto size = _sb1->sgetn(_buf.data(), _buf.size()))
return size;
_insb1 = false;
}
return _sb2->sgetn(_buf.data(), _buf.size());
}();
setg(_buf.data(), _buf.data(), _buf.data() + size);
}
return gptr() == egptr()
? std::char_traits<char>::eof()
: std::char_traits<char>::to_int_type(*gptr());
}
};
void print(std::istream &in) { // function not to be modified
std::string str;
while (in >> str)
std::cout << str << std::endl;
}
int main() {
std::stringbuf header("hello ");
cat_streambuf both(&header, std::cin.rdbuf());
std::istream is(&both);
print(is);
}
Which also prints
hello
foo
bar
qux
for the same input. This will definitely scale better for (very) large streams.