So, I started an indenting buffer/ostream,setting the indent level using manipulators and run into problems... The first was the compiler error indent_ostream& increase(indent_ostream&)' will always evaluate as 'true'
. Just made a operator<< for function pointers as member of the ostream. The next than was ambiguous overload for 'operator<<' (operand types are 'indent_ostream' and 'int')
. Also added a member operator<< with templated argument to catch all types to be streamed (string, int, etc).This results into an Segmentation fault
and here I am :(
#include <iostream>
#include <streambuf>
#include <iomanip>
class indent_sbuf : public std::streambuf
{
std::streambuf* m_sbuf;
std::string m_indent_str;
bool m_start_of_line;
static const int TAB_WIDTH = 4;
public:
explicit indent_sbuf(std::streambuf* sbuf, size_t indent = 0)
: m_sbuf{ sbuf }
, m_indent_str(indent, ' ')
, m_start_of_line{ true }
{ }
~indent_sbuf()
{
overflow('\n');
}
indent_sbuf& increase()
{
m_indent_str = std::string(m_indent_str.size() + TAB_WIDTH, ' ');
return *this;
}
indent_sbuf& decrease()
{
if(m_indent_str.size() > TAB_WIDTH) {
m_indent_str = std::string(m_indent_str.size() - TAB_WIDTH, ' ');
}
else {
m_indent_str = "";
}
return *this;
}
private:
int_type overflow(int_type chr) override
{
if (m_start_of_line && chr != '\n') {
m_sbuf->sputn( m_indent_str.data(), m_indent_str.size() );
}
m_start_of_line = (chr == '\n');
return m_sbuf->sputc( chr );
}
};
class indent_ostream : public std::ostream
{
indent_sbuf buf;
public:
indent_ostream(std::ostream& os, size_t width)
: std::ostream(&buf)
, buf(os.rdbuf(), width)
{ }
indent_ostream& operator<<(indent_ostream& (*fcn)(indent_ostream&))
{
return (*fcn)(*this);
}
template<typename T>
indent_ostream& operator<<(T const& v) // get it to compile
{
*this << v; // but crash
return *this;
}
};
static inline
indent_ostream& increase(indent_ostream& os)
{
indent_sbuf* buf = static_cast<indent_sbuf*>(os.rdbuf());
buf->increase();
return os;
}
static inline
indent_ostream& decrease(indent_ostream& os)
{
indent_sbuf* buf = static_cast<indent_sbuf*>(os.rdbuf());
buf->decrease();
return os;
}
int main()
{
indent_ostream os(std::cout, 0);
os << "Hallo\n";
os << increase << "World\n";
os << decrease << 42 << "\n";
}
Also at coliru. So, what going on here and where are my faults? How to get it working correct and standard conforming?
Aucun commentaire:
Enregistrer un commentaire