I was spinning my head around how to do the same thing and i found out it’s actually not that hard.
Basically just subclass the ostream and the streambuf objects, and construct the ostream with itself as the buffer. the virtual overflow() from std::streambuf will be called for every character sent to the stream. To fit your example i just made a foo() function and called it.
#include <iostream>
struct Bar : private std::streambuf , public std::ostream
{
Bar() : std::ostream(this) {}
private:
int overflow(int c) override
{
foo(c);
return 0;
}
void foo(char c)
{
std::cout.put(c);
}
};
int main()
{
Bar b;
b<<"Look a number: "<<std::hex<<29<<std::endl;
return 0;
}
EDIT: The old code used the wrong initialization order. Although it had no visible side effects, the streambuf object should be initialized before passing it to the ostream object. Since C++ initializes parents left to right, I moved std::streambuf to the left to make the code correct.
EDIT: I changed the code to inherit std::streambuf privately to keep the interface cleaner and keep the class encapsulated.