boost::streams::output过滤器的意外行为
Unexpected behavior with boost::streams::output filter
我正在尝试实现日志记录的输出过滤器,并修改了一些示例代码,结果出乎意料。代码是
#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)'在第一次调用结构成员函数时求值一次。我希望每次有东西流到'out '时都对它进行评估。
作为题外话,我正在研究一些记录到控制台(或者可能是一个文件)的东西,并具有基于位图过滤的能力。现在,将定义一个掩码并在其中设置位,以使特定的输出语句能够实际写入内容。代码可能看起来像这样(其中mask为enable)
<sometype> mask(0x0101);
out << enable(0x0010) << "log message" << endl; // not output
out << enable(0x0100) << "another log message" << endl; // is output
这似乎是一种常见的事情,一个开发人员可能想要做,但我无法找到一个例子来复制。我正在寻找一个解决方案,然后遇到了这个。
谢谢!
编辑:试图通过添加setPri类来使用一个参数来添加到尼基塔建议的解决方案中。所有输出都被缓存,直到程序退出,然后最后一次setPri()插入生效。Boost iostreams应该是这样工作的吗?
#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
这里的问题是pri
变量变为2
后,toupper_output_filter
应用于输出序列。
语句out << "test-1" << endl;
不过滤序列,它将符号放入缓冲区以供进一步处理。之后,pri=2;
和更多的符号进入out << "test-2" << endl;
的缓冲区。在离开作用域之前,out
过滤它的缓冲区并输出最终的符号序列。此时pri
是2
,所有行都打印出来了。
要解决这个问题,你可以删除全局状态:
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++集合
- 在C++中对T*类型执行std::move的意外行为
- 使用取消引用的指针的多态性会产生意外的结果.为什么?
- 处理除以零会导致<csignal>意外行为
- vscode下的Arduino代码出现意外编译错误
- 使用++运算符会导致意外的结果
- 套接字读取后,我在缓冲区中看到意外输入
- 更改.cpp程序的输入文件中数据的位置会意外更改输出
- 使用vscode调试时,GDB意外退出
- 如何将字符串添加到布谷鸟过滤器?
- 此测试()中发生了什么意外过程?为什么总是覆盖 ch[0 1 2..]?
- 尝试将字符串/字符转换为整数会产生意外结果
- 错误 C2760:语法错误:映射迭代器上意外的标记"标识符",预期的";"
- C++标头错误 C2238 意外标记";"
- C++中意外的多头值
- vector.size() 在比较中意外工作
- 使用 malloc() 时出现意外大小
- 多线程程序中出现意外的内存泄漏
- 为什么static_cast基础类型的枚举类int8_t获得意外值?
- boost::streams::output过滤器的意外行为