gpt4 book ai didi

c++ - boost::streams::output 过滤器的意外行为

转载 作者:搜寻专家 更新时间:2023-10-31 02:14:39 25 4
gpt4 key购买 nike

我正在尝试为日志记录实现一个输出过滤器,并修改了一些示例代码,但结果却出乎意料。代码是

#include <ctype.h>                        // toupper
#include <boost/iostreams/categories.hpp> // output_filter_tag
#include <boost/iostreams/operations.hpp> // put
#include <boost/iostreams/filtering_stream.hpp>

// cobbled from http://www.boost.org/doc/libs/1_48_0/libs/iostreams/doc/concepts/output_filter.html#examples
//
// g++ [-DTEST] -o t-pri t-pri.cpp

using namespace std;
namespace io = boost::iostreams;

int pri=4;

struct toupper_output_filter {
typedef char char_type;
typedef io::output_filter_tag category;

template<typename Sink>
bool put(Sink& snk, char c)
{
if(pri<3)
return io::put(snk, /* toupper((unsigned char) c)*/ c);
else
return 0;
}
};

int main(int argc, char**argv)
{
boost::iostreams::filtering_ostream out;

out.push(toupper_output_filter());
cout << "pri: " << pri << endl;
out.push(cout);

out << "test-1" << endl;
#ifdef TEST
pri=2;
out << "test-2" << endl;
#endif
return 0;
}

定义 TEST 宏时遇到意外行为:

hbarta@itws007:~/Documents/C++/t-pri$ g++ -o t-pri t-pri.cpp
hbarta@itws007:~/Documents/C++/t-pri$ ./t-pri
pri: 4
hbarta@itws007:~/Documents/C++/t-pri$ g++ -DTEST -o t-pri t-pri.cpp
hbarta@itws007:~/Documents/C++/t-pri$ ./t-pri
pri: 4
test-1
test-2
hbarta@itws007:~/Documents/C++/t-pri$

似乎表达式“if(pri<3)”在首次调用结构成员函数时被求值一次。我希望每次有内容流式传输到“输出”时都会对其进行评估。

顺便说一句,我正在努力开发一些可以记录到控制台(或者可能是一个文件)并且能够基于位图进行过滤的东西。 IOW,将定义一个掩码并在其中设置位,以使特定的输出语句能够实际写入某些内容。代码可能看起来像(掩码与启用一起使用)

<sometype> mask(0x0101);
out << enable(0x0010) << "log message" << endl; // not output
out << enable(0x0100) << "another log message" << endl; // is output

这似乎是开发人员可能想要做的常见事情,但我找不到可复制的示例。我正在努力寻找解决方案并遇到了这个问题。

谢谢!

编辑:尝试根据 Nikita 的建议添加 setPri 类以用作带有参数的 iomanip 来添加到解决方案中。仍未按预期工作 所有输出都被缓存,直到程序退出,然后最后一次 setPri() 插入生效。这就是 Boost iostream 的工作方式吗?

#include <boost/iostreams/categories.hpp> // output_filter_tag
#include <boost/iostreams/operations.hpp> // put
#include <boost/iostreams/filtering_stream.hpp>

using namespace std;
namespace io = boost::iostreams;

// cobbled from http://www.boost.org/doc/libs/1_48_0/libs/iostreams/doc/concepts/output_filter.html#examples
//
// g++ -o to_upper to_upper.cpp
//
// Adding an iomanip with argument as in
// http://stackoverflow.com/questions/20792101/how-to-store-formatting-settings-with-an-iostream


// don't really want file scope variables...
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();
pri = n;
os << "setPri(" << n << ")"; // indicate update
return os;
}
};

struct toupper_output_filter {
typedef char char_type;
typedef io::output_filter_tag category;

template<typename Sink>
bool put(Sink& snk, char c)
{
if(pri & mask) // Should this char be sent to output?
return io::put(snk, c);
else
return 0;
}
};

int main(int argc, char**argv)
{
boost::iostreams::filtering_ostream out;

out.push(toupper_output_filter());
out.push(cout);

out << setPri(1) << " test-1" << endl;
out << setPri(2) << " test-2" << endl;
out << setPri(3) << " test-3" << endl;
return 0;
}

结果是

setPri(1) test-1
setPri(2) test-2
setPri(3) test-3

最佳答案

这里的问题是 toupper_output_filter应用于 pri 之后的输出序列变量更改为 2 .

声明out << "test-1" << endl;不过滤序列,它将符号放入缓冲区以进行进一步处理。之后pri=2;更多符号进入缓冲区 out << "test-2" << endl; .离开范围前out过滤它的缓冲区并输出最终的符号序列。此时pri2以及打印的所有行。

要解决此问题,您可以删除全局状态:

struct toupper_output_filter {
typedef char char_type;
typedef io::output_filter_tag category;

int pri;
toupper_output_filter (int logLevel)
{
pri = logLevel;
}

template<typename Sink>
bool put(Sink& snk, char c)
{
if(pri<3)
return io::put(snk, /* toupper((unsigned char) c)*/ c);
else
return 0;
}
};

并使用它:

int main(int argc, char**argv)
{
boost::iostreams::filtering_ostream out;

int pri = 4;
out.push(toupper_output_filter(pri));
cout << "pri: " << pri << endl;
out.push(cout);

out << "test-1" << endl;
out.pop();
out.pop();

#ifdef TEST
pri=2;

out.push(toupper_output_filter(pri));
out.push(cout);
out << "test-2" << endl;
#endif
return 0;
}

更新:setPri的主要思想类是删除静态并使用 operator<< 操纵优先级.解决方案草案:

static int mask=1;      // mask for enabled output (if pri&mask => output)

struct toupper_output_filter {
typedef char char_type;
struct category : boost::iostreams::output_filter_tag {};

int pri;
toupper_output_filter(int n)
{
pri = n;
}

template<typename Sink>
bool put(Sink& snk, char c)
{
if(pri & mask) // Should this char be sent to output?
return io::put(snk, c);
else
return 0;
}
};

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 boost::iostreams::filtering_ostream& operator<<(boost::iostreams::filtering_ostream& out, const setPri& obj)
{
if (!out.empty())
{
out.pop();
out.pop();
}
out.push(toupper_output_filter(obj.getn()));
out.push(cout);
return out;
}
};

int main(int argc, char**argv)
{
boost::iostreams::filtering_ostream out;

out << setPri(1) << " test-1" << endl;
out << setPri(2) << " test-2" << endl;
out << setPri(3) << " test-3" << endl;
return 0;
}

输出是:

 test-1
test-3

关于c++ - boost::streams::output 过滤器的意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39712154/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com