ログ出力用のフィルタを実装しようとしていて、予期しない結果が発生したサンプルコードが変更されました。コードはTESTマクロが定義されている場合、予期しない動作が発生したboost :: streams ::出力フィルタで予期しない動作が発生しました
#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
ようになります。私は解決策に向かって作業しており、これに遭遇しました。
ありがとうございます!
編集:Nikitaの提案に従ってソリューションに追加しようとすると、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
。私が見つけた資料によると、 "その動作は、char以外の文字型のos.put( '\ n')(またはos.put(os.widen( '\ n'))の呼び出しと同じです。次にos.flush()を呼び出します。 私はendlが出力をフラッシュし、それが明らかに出力されないことを期待します。 ありがとう! – HankB
あなたの 'enable(0x0010)'目標を達成するには、 'enable'とoverload [' operator << ']のユーザ定義型の作成を試みることができます(http://en.cppreference.com/w/cpp/language /演算子)を指定します。このオーバーロードは、適切な 'toupper_output_filter'インスタンスで' pop() '/' push() 'を行います。 – Nikita
ありがとう、私はそれに行きましたが、まだ結果が期待されていません。私のOPへの私の追加を見てください。 – HankB