Is there a way to add a custom prefix in the operator<< for an object that I implement?
Ex:
class A {
   public:
    std::string id;
    int count;
};
std::ostream &operator<<(std::ostream &os, const A &a)
{
    os << os.prefix() << "Id: " << a.id << "\n";
    os << os.prefix() << "Count: " << a.count << "\n";
    return os;
}
If I do something like this:
A a;
a.id = "foo";
a.count = 1;
std::cout << a << std::endl;
The output will be:
Id: foo
Count: 1
I want to do something like:
std::cout << set_prefix(" -") << a << std::endl;
std::cout << set_prefix("==>") << a << std::endl;
To get an output like this:
 -Id: foo
 -Count: 1
==>Id: foo
==>Count: 1
A suggestion is to use std::setfill and os.fill, but std::setfill takes a single char as an argument and I need a custom string instead.
Looking at operator<<(std::basic_ostream) documentation, I found this:
Before insertion, first, all characters are widened using
os.widen(), then padding is determined as follows: if the number of characters to insert is less thanos.width(), then enough copies ofos.fill()are added to the character sequence to make its length equalos.width(). If(out.flags()&std::ios_base::adjustfield) == std::ios_base::left, the fill characters are added at the end of the output sequence, otherwise they are added before the output sequence. After insertion,width(0)is called to cancel the effects ofstd::setw, if any.
So the solution that works for me was save the original width of stream at the beggining and than recovering them when necessary.
std::ostream &operator<<(std::ostream &os, const A &a)
{
    auto w = os.width();
    os << std::setw(w) << "" << "Id: " << a.id << "\n";
    os << std::setw(w) << "" << "Count: " << a.count;
    return os;
}
Then:
std::cout << a << std::endl;
std::cout << std::setw(4) << a << std::endl;
std::cout << std::setfill('>') << std::setw(2) << a << std::endl;
Gave the following output:
Id: foo
Count: 1
    Id: foo
    Count: 1
>>Id: foo
>>Count: 1
                Maybe a bit of overkill, but you can use something like this:
#include <iostream>
#include <sstream>
struct line_buffered_stream {
    std::ostream& out;
    std::stringstream ss;
    std::string prefix;
    line_buffered_stream(std::ostream& out,std::string prefix) : 
        out(out),prefix(prefix) {}        
    template <typename T> 
    auto operator<<(const T& t) -> decltype(this->ss << t,*this) { 
        ss << t; 
        return *this;
    }        
    ~line_buffered_stream(){
        std::string line;
        while (std::getline(ss,line)){
            out << prefix << line << "\n";
        }
    }
};
int main() {
     line_buffered_stream(std::cout,"==>") << "a\nb\n";
     line_buffered_stream(std::cout,"-->") << "a\nb\n";        
}
output:
==>a
==>b
-->a
-->b
Live Demo
Note that the implementation above is not meant to be used as anything else than a temporary whose lifetime is restricted to a single line of code. If you dont like that you'd have to add some mechanism to flush the stream to std::cout not to wait till the destructor is called.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With