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

Unexpected results from ios_base::xalloc() and ostream::iword() (iomanip)

本文关键字:iomanip iword 意外 结果 ostream xalloc ios 来自 base      更新时间:2023-10-16

我的目标是拥有一个带有参数的iomanip插入器,该插入器可用于确定是否将消息打印到流中(或不打印)。这个想法是,静态掩码将包括为应该流式传输的消息类别设置的位(以及为要丢弃的消息清除的位)。插入器将用于指定消息属于哪个类别(或多个类别),如果与所呈现的类别匹配的掩码不为零,则消息将被流输出。我有这个工作,但与文件范围掩码和类别。在我看来(至少类别)可以使用xalloc()与流一起存储,以提供索引和iword()在该索引处存储/检索值,但这似乎不适合我。我已经阅读了关于这些函数的各种互联网参考资料,我的期望是对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。请随意建议一个更好的选择!)那我能理解。;)

谢谢!

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

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

iword数据的存储是动态的,当有东西存储在那里时,由每个流对象单独分配。