I want an istream that you can safely peek arbitrarily many characters from. This works as far as I can tell, but I am unsure if this is really "the right way" to do it since the iostream library is pretty cryptic to me.

class peekbuf : public std::streambuf
    std::streambuf* sbuf_;
    std::vector<char> data_;
    char ch; 
    peekbuf(std::streambuf* s)
    : sbuf_(s)
    { } 

    std::vector<char> const& peek(int N) {
        for (int i = 0; i < N; ++i) {
            int next = sbuf_->sbumpc();
            if (next == traits_type::eof()) {

        if (!data_.empty()) {
            setg(data_.data(), data_.data(), data_.data() + data_.size());

        return data_;

    int_type underflow() override {
        ch = sbuf_->sbumpc();
        setg(&ch, &ch, &ch + 1); 
        return ch; 

Example usage:

int main() {
    peekbuf buf{std::cin.rdbuf()};

    auto first5 = buf.peek(5);

    std::string s;
    std::cin >> s;
    std::cout << "Got " << s << '\n';

    std::cout << "Peeked: ";
    for (char c : first5) {
        std::cout << c;
    std::cout << '\n';


$ echo 123456789 | ./a.out


Got 123456789
Peeked: 12345
  • \$\begingroup\$ I don;t have time write now (this weekend). But something feels wrong. When you set the underlying buffer with setg(data_.data(), data_.data(), data_.data() + data_.size()); I would expect you to save the state of the current buffer so when you have finished reading your peeked data you can go back to the original buffer. \$\endgroup\$ – Martin York May 5 '16 at 17:33
  • \$\begingroup\$ You don't need to go back to the original, you've just set the internal buffer to a new valid state. The only downside here is, of course, that regular i/o buffers support "unget" which setg supports by setting the first two arguments nonequal. You may find that this peek class interferes with operations of some parsers, etc. \$\endgroup\$ – Erik Aronesty Nov 6 '19 at 13:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.