带缩进的c ++自定义输出流

use*_*153 9 c++ stl derived stream manipulators

我在尝试实现自定义流类以在输出文件中生成漂亮的缩进代码时遇到了一些麻烦.我在网上广泛搜索,但似乎没有就实现这一目标的最佳方式达成共识.有些人谈论派生流,其他人谈论推导缓冲,而其他人建议使用locales/facets等.

基本上,我发现自己写了很多这样的代码:

ofstream myFile();
myFile.open("test.php");
myFile << "<html>" << endl <<
          "\t<head>" << endl <<
          "\t\t<title>Hello world</title>" << endl <<
          "\t</head>" << endl <<
          "</html>" << endl;
Run Code Online (Sandbox Code Playgroud)

当标签开始加起来时,它看起来很糟糕,看起来像这样的东西会很好:

ind_ofstream myFile();
myFile.open("test.php");
myFile << "<html>" << ind_inc << ind_endl <<
          "<head>" << ind_inc << ind_endl <<
          "<title>Hello world</title>" << ind_dec << ind_endl <<
          "</head>" << ind_dec << ind_endl <<
          "</html>" << ind_endl;
Run Code Online (Sandbox Code Playgroud)

即创建一个派生流类,它将跟踪其当前的缩进深度,然后一些操纵器增加/减少缩进深度,一个操纵器编写一个换行符,然后是多个标签.

所以这是我实现类和操纵器的镜头:

ind_ofstream.h

class ind_ofstream : public ofstream
{
    public:
        ind_ofstream();
        void incInd();
        void decInd();
        size_t getInd();

    private:
        size_t _ind;
};

ind_ofstream& inc_ind(ind_ofstream& is);
ind_ofstream& dec_ind(ind_ofstream& is);
ind_ofstream& endl_ind(ind_ofstream& is);
Run Code Online (Sandbox Code Playgroud)

ind_ofstream.cpp

ind_ofstream::ind_ofstream() : ofstream()   {_ind = 0;}
void ind_ofstream::incInd()     {_ind++;}
void ind_ofstream::decInd()     {if(_ind > 0 ) _ind--;}
size_t ind_ofstream::getInd()       {return _ind;}

ind_ofstream& inc_ind(ind_ofstream& is)     
{ 
    is.incInd();
    return is; 
}

ind_ofstream& dec_ind(ind_ofstream& is)     
{ 
    is.decInd();
    return is; 
}

ind_ofstream& endl_ind(ind_ofstream& is)    
{
    size_t i = is.getInd();
    is << endl;
    while(i-- > 0) is << "\t";
    return is;
}
Run Code Online (Sandbox Code Playgroud)

这会构建,但不会产生预期的输出; 任何使用自定义操纵器的尝试都会导致它们由于某种原因被强制转换为布尔值,并且"1"写入文件.我是否需要为我的新类重载<<运算符?(我无法找到这样做的方法)

谢谢!

PS

1)我省略了#includes,使用我的代码片段中的命名空间等来节省空间.

2)我的目标是能够使用类似于我的第二个代码片段中的界面.如果在阅读完整篇文章后,您认为这是一个坏主意,请解释原因并提供替代方案.

Bar*_*nau 8

iostream支持向它们添加自定义数据,因此您不需要编写完整的派生类,只需添加将由操作符操作的缩进级别.这是iostreams鲜为人知的特色,但在这里派上用场.

你会像这样编写你的操纵器:

/* Helper function to get a storage index in a stream */
int get_indent_index() {
    /* ios_base::xalloc allocates indices for custom-storage locations. These indices are valid for all streams */
    static int index = ios_base::xalloc();
    return index;
}

ios_base& inc_ind(ios_base& stream) {
    /* The iword(index) function gives a reference to the index-th custom storage location as a integer */
    stream.iword(get_indent_index())++;
    return stream;
}

ios_base& dec_ind(ios_base& stream) {
    /* The iword(index) function gives a reference to the index-th custom storage location as a integer */
    stream.iword(get_indent_index())--;
    return stream;
}

template<class charT, class traits>
basic_ostream<charT, traits>& endl_ind(basic_ostream<charT, traits>& stream) {
    int indent = stream.iword(get_indent_index());
    stream.put(stream.widen('\n');
    while (indent) {
        stream.put(stream.widen('\t');
        indent--;
    }
    stream.flush();
    return stream;
}
Run Code Online (Sandbox Code Playgroud)