来自ios_base :: xalloc()和ostream :: iword()(iomanip)的意外结果

时间:2016-09-28 17:17:08

标签: c++ iomanip

我的目标是让一个带有参数的iomanip插件可以用来确定是否将一条消息打印到流中(或不是。)这个想法是静态掩码将包含为消息类别设置的位。应该流式传输(并清除位以便丢弃消息。)插入器将用于指定消息所属的类别(或类别),如果使用所呈现的类别的掩码不为零,则消息将被流出。我有这个工作,但有文件范围掩码和类别。在我看来,(至少类别)可以使用xalloc()来存储流,以提供索引和iword()来存储/检索该索引处的值,但这似乎对我不起作用。我已经阅读了这些函数的各种Internet引用,我的期望是对xalloc()的顺序调用应返回增加的值。在下面的代码中,返回的值始终为4.我的第二个难题是保存iword()后备存储的存储。对于ostream来说这是静态的吗?每个ostream对象的一部分?

代码如下

#include <iostream>
#include <sstream>
// from http://stackoverflow.com/questions/2212776/overload-handling-of-stdendl
//
// g++ -o blah blah.cpp
//
// Adding an iomanip with argument as in 
// http://stackoverflow.com/questions/20792101/how-to-store-formatting-settings-with-an-iostream
//

using namespace std;

// don't really want file scope variables... Can these be stored in stream?
static int pri=0;       // value for a message
static int mask=1;      // mask for enabled output (if pri&mask => output)

static int priIDX() {   // find index for storing priority choice
    static int rc = ios_base::xalloc();
    return rc;
}

class setPri // Store priority in stream (but how to retrieve when needed?)
{
    size_t _n;
public:
    explicit setPri(size_t n): _n(n) {}
    size_t getn() const {return _n;}
    friend ostream& operator<<(ostream& os, const setPri& obj)
    {
        size_t n = obj.getn();
        int ix = priIDX();
        pri = os.iword(ix) = n;     // save in stream (?) and to file scope variable
        os << "setPri(" << n << ") ix:" << ix << " ";       // indicate update
        return os;
    }
};

class MyStream: public ostream
{
    // Write a stream buffer that discards if mask & pri not zero
    class MyStreamBuf: public stringbuf
    {
        ostream&   output;
        public:
            MyStreamBuf(ostream& str)
                :output(str)
            {}

        // When we sync the stream with the output. 
        // 1) report priority mask (temporary)
        // 2) Write output if same bit set in mask and priority
        // 3) flush the actual output stream we are using.
        virtual int sync ( )
        {
            int ix = priIDX();

            int myPri(output.iword(ix));
            output << "ix:" << ix << " myPri:" << myPri << '\n';

            if( mask & pri) // can't use (myPri&mask)
                output << ' ' << str();
            str("");
            output.flush();
            return 0;
        }
    };

    // My Stream just uses a version of my special buffer
    MyStreamBuf buffer;
    public:
        MyStream(ostream& str)
            :buffer(str)
        {
            rdbuf(&buffer);
        }
};

int main()
{
    MyStream myStream(cout);
    myStream << setPri(1) << " this should output" << endl;
    myStream << setPri(2) << " this should not output" << endl;
    myStream << setPri(3) << " this should also output" << endl;
}

请注意,在sync()中,代码尝试从流中获取值,但返回的值始终为0,就像它未设置为开始一样。

在我的搜索中达到这一点,我看到了一些评论,即子类化ostream不是一个好主意。随意提出更好的选择! (我能理解。;))

谢谢!

1 个答案:

答案 0 :(得分:2)

static int priIDX() {   // find index for storing priority choice
    static int rc = ios_base::xalloc();
    return rc;
}

这将始终返回相同的值,因为您的值是静态的。因此只在第一次通话时初始化。

iword数据的存储是动态的,并且每当存储某些内容时,每个流对象都会单独分配。