Я пытаюсь реализовать выходной фильтр для ведения журнала и изменил код примера с неожиданными результатами. КодНеожиданное поведение с 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;
}
неожиданное поведение возникает, когда ТЕСТ макрокоманда определена:
[email protected]:~/Documents/C++/t-pri$ g++ -o t-pri t-pri.cpp
[email protected]:~/Documents/C++/t-pri$ ./t-pri
pri: 4
[email protected]:~/Documents/C++/t-pri$ g++ -DTEST -o t-pri t-pri.cpp
[email protected]:~/Documents/C++/t-pri$ ./t-pri
pri: 4
test-1
test-2
[email protected]:~/Documents/C++/t-pri$
Кажется, что выражение «если (PRI < 3)» вычисляется один раз, когда элемент структуры функция сначала вызывается. Я ожидаю, что он будет оцениваться каждый раз, когда что-то потокочет на «выход».
Как в стороне, я работаю над тем, что записывается на консоль (или, возможно, файл), и имеет возможность фильтровать на основе растрового изображения. IOW, будет определена маска и биты, установленные в ней, чтобы позволить конкретным операторам вывода фактически что-то писать. Код может выглядеть следующим образом (где маска с операцией AND включить)
<sometype> mask(0x0101);
out << enable(0x0010) << "log message" << endl; // not output
out << enable(0x0100) << "another log message" << endl; // is output
Это похоже на общий вид вещи, которые разработчик может захотеть сделать, но я не могу найти пример для копирования. Я работаю над решением и сталкивался с этим.
Спасибо!
Редактировать: Пытается добавить к решению предложение Никиты, добавив класс setPri для использования в качестве iomanip с аргументом. Все еще не работает, как ожидалось. Все выходные данные кэшируются до выхода программы, а затем вступает в действие последняя вставка 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
Это объясняет поведение, но я не уверен, что это имеет смысл для меня.Согласно материалу, я нахожу его в строке «Его поведение эквивалентно вызову os.put ('\ n') (или os.put (os.widen ('\ n')) для типов символов, отличных от char), и затем os.flush(). " Я бы ожидал, что endl сбросит выход, но, тем не менее, это не так. Спасибо! – HankB
Чтобы достичь цели 'enable (0x0010)', вы можете попытаться создать пользовательский тип для 'enable' и overload [' operator << '] (http://en.cppreference.com/w/cpp/language/операторов) с этим типом в качестве параметра. Эта перегрузка будет делать все 'pop()'/'push()' с соответствующим экземпляром 'toupper_output_filter'. – Nikita
Спасибо, я пошла на это и все еще не надеялась на результаты. Пожалуйста, ознакомьтесь с моими дополнениями к моему OP. – HankB