1

I was wondering if there is a way to "block" the cout output either for the few next characters or the next command. I have a function that I can't change with a print in the beginning and would like to override that next print.

void overridePrint(){
    std::cout << "Replaced header" << std::endl;
    print();   //prints another header
}
void print(){
    std::cout << "Normal header" << std::endl;
    std::cout << "other prints";
    //...
}

I know there is a way to temporarily disable the output, but since i can't modify the print function to enable it after the first print, i don't really know what to do. Could just copy the entire function but thats just not nice.

vincnt0
  • 13
  • 3
  • std::endl triggers a cout buffer flush. – JGroven Mar 27 '18 at 21:45
  • 1
    So you want to completely prevent `Normal header` from appearing? I don't think there's any way to do that. – Barmar Mar 27 '18 at 21:47
  • This doesn't address the question, but you probably don't need the extra stuff that `std::endl` does. `'\n'` ends a line. – Pete Becker Mar 27 '18 at 21:50
  • Maybe you could temporarily redirect the output using [`rdbuf`](http://en.cppreference.com/w/cpp/io/basic_ios/rdbuf). I think the example code there does exactly what you want. – Fred Larson Mar 27 '18 at 21:54
  • @PeteBecker ok thanks, im gonna look into what the differences are :) – vincnt0 Mar 27 '18 at 21:55
  • @FredLarson the problem is that i'd have to add the `std::cout.rdbuf(cout_buff);` into the print function, which technically wouldn't change the functionality of it, but i dont really want to change the print function (it's a given library function). – vincnt0 Mar 27 '18 at 22:01
  • Let this be a reminder to everyone: separate concerns in separate functions. Composing behavior is easy; restricting it from the outside is difficult if not impossible. In particular, I/O is irreversible and its disposition is the business of `main` (Haskell gets this right by making it part of a function’s signature). – Davis Herring Mar 28 '18 at 01:46

1 Answers1

2

I was curious, and wrote this proof of concept inspired by this code review https://codereview.stackexchange.com/q/104428/38143 post. It's probably silly hack to use std::codecvt for this, and the code may contain bugs, so use at your own risk:

#include <locale>
#include <algorithm>
#include <iostream>
#include <iomanip>

class swallow_line_facet : public std::codecvt<char, char, std::mbstate_t> {
public:
    swallow_line_facet(std::size_t ref = 0)
        : std::codecvt<char, char, std::mbstate_t>(ref) {}

protected:
    result do_out(
        state_type &,
        const intern_type* from,
        const intern_type* from_end,
        const intern_type*& from_next,
        extern_type* to,
        extern_type* to_end,
        extern_type*& to_next) const override
    {
        if (is_done)
            return std::codecvt_base::noconv;

        for (; (from < from_end) && (to < to_end); from++) {
            char c = *from;

            if (is_done)
                *to++ = c;

            if (c == '\n')
                is_done = true;
        }

        from_next = from;
        to_next = to;

        return from == from_end
            ? std::codecvt_base::ok
            : std::codecvt_base::partial;
    }

    virtual bool do_always_noconv() const noexcept override {
        return is_done;
    }

private:
    mutable bool is_done = false;
};

std::ostream& swallow_line(std::ostream& out)
{
    out.imbue(std::locale(out.getloc(), new swallow_line_facet));
    return out;
}

Demo

int main() {
    /// This probably has to be called once for every program:
    // http://stackoverflow.com/questions/26387054/how-can-i-use-stdimbue-to-set-the-locale-for-stdwcout
    std::ios_base::sync_with_stdio(false);

    std::cout << "first line" << '\n' << swallow_line;
    std::cout << "second line" << '\n';
    std::cout << "third line" << '\n' << swallow_line;
    std::cout << "fourth line" << '\n';
    std::cout << "fifth line" << '\n';
}

Output:

first line
third line
fifth line

Usage in your case:

void overridePrint(){
    std::cout << "Replaced header" << std::endl;
    std::cout << swallow_line;
    print();
}

int main() {
    /// don't forget this
    std::ios_base::sync_with_stdio(false);
    // ...
}
eerorika
  • 232,697
  • 12
  • 197
  • 326