所以,我启动了一个缩进缓冲区/ ostream,使用操纵器设置缩进级别并遇到问题......首先是编译错误
indent_ostream& increase(indent_ostream&)' will always evaluate as 'true'
。刚做了一个算子&lt;&lt;将函数指针作为ostream的成员。下一个是ambiguous overload for 'operator<<' (operand types are 'indent_ostream' and 'int')
。还添加了一个成员运算符&lt;&lt;使用模板化参数来捕获所有要流式传输的类型(字符串,整数等)。这导致Segmentation fault
,我在这里:(
#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";
}
同样在coliru。那么,这里发生了什么,我的错在哪里?如何让它正常工作并符合标准?
答案 0 :(得分:3)
所以你收到了警告:
第一个是编译器错误
indent_ostream& increase(indent_ostream&)'
将始终评估为'true'
为什么呢?那是什么意思? os << increase
实际上做了什么?不要忽视警告!它指出你的代码中存在真正的问题!究!
如果你查看operator<<
的运算符列表,就会出现这个:
basic_ostream& operator<<(
std::basic_ostream<CharT,Traits>& (*func)(std::basic_ostream<CharT,Traits>&) );
但是那个与你的功能不匹配,它不是一个可行的候选人。函数Derived&(*)(Derived&)
与Base&(*)(Base&)
不匹配 - 它永远不会有效。相反,最好(唯一)可行的候选人是:
basic_ostream& operator<<( bool value );
因为函数指针可以转换为bool
。警告是这很愚蠢,因为很明显这会打印1
,可能不是你打算做的。
但实际上 该函数无论如何都不需要indent_ostream
。你关心的只是缓冲区。所以解决方案是修复你的修饰符以匹配预期的签名:
static inline std::ostream& increase(std::ostream& os)
{
indent_sbuf* buf = static_cast<indent_sbuf*>(os.rdbuf());
buf->increase();
return os;
}
static inline std::ostream& decrease(std::ostream& os)
{
indent_sbuf* buf = static_cast<indent_sbuf*>(os.rdbuf());
buf->decrease();
return os;
}
现在,它有效!