Escribiendo un manipulador para una clase de flujo personalizado
He escrito una clase de flujo personalizado que genera texto con sangría y que tiene manipuladores que pueden cambiar el nivel de sangría. Todo el trabajo de sangrado se implementa en una clase de búfer de flujo personalizada, que es utilizada por la clase de flujo. El búfer está funcionando (es decir, el texto está sangrado en la salida), pero no puedo hacer que funcionen mis manipuladores. Estaba leyendo en muchos lugares cómo ostream (que mi clase extiende) sobrecarga al operador << de esta manera:
ostream& ostream::operator << ( ostream& (*op)(ostream&))
{
// call the function passed as parameter with this stream as the argument
return (*op)(*this);
}
Lo que significa que puede tomar en una función como un parámetro. Entonces, ¿por qué no se reconocen mis funciones de secuencia "sangradas" o "desindentadas"? Estoy seguro de que tengo que sobrecargar al operador <<, pero ¿no debería no necesitarlo? Vea a continuación mi código:
#include <iostream>
#include <streambuf>
#include <locale>
#include <cstdio>
using namespace std;
class indentbuf: public streambuf {
public:
indentbuf(streambuf* sbuf): m_sbuf(sbuf), m_indent(4), m_need(true) {}
int indent() const { return m_indent; }
void indent() { m_indent+=4; }
void deindent() { if(m_indent >= 4) m_indent-= 4; }
protected:
virtual int_type overflow(int_type c) {
if (traits_type::eq_int_type(c, traits_type::eof()))
return m_sbuf->sputc(c);
if (m_need)
{
fill_n(ostreambuf_iterator<char>(m_sbuf), m_indent, ' ');
m_need = false;
}
if (traits_type::eq_int_type(m_sbuf->sputc(c), traits_type::eof()))
return traits_type::eof();
if (traits_type::eq_int_type(c, traits_type::to_char_type('\n')))
m_need = true;
return traits_type::not_eof(c);
}
streambuf* m_sbuf;
int m_indent;
bool m_need;
};
class IndentStream : public ostream {
public:
IndentStream(ostream &os) : ib(os.rdbuf()), ostream(&ib){};
ostream& indent(ostream& stream) {
ib.indent();
return stream;
}
ostream& deindent(ostream& stream) {
ib.deindent();
return stream;
}
private:
indentbuf ib;
};
int main()
{
IndentStream is(cout);
is << "31 hexadecimal: " << hex << 31 << endl;
is << "31 hexadecimal: " << hex << 31 << endl;
is << "31 hexadecimal: " << hex << 31 << deindent << endl;
return 0;
}
¡Gracias!