0

演算子<<を介して入力を受け取り、次のようなカスタムマニピュレーターを受け取った後に監査を書き込む単純な監査クラスを作成しようとしています。

class CAudit
{
public:
    //needs to be templated
    CAudit& operator << ( LPCSTR data ) {
        audittext << data;
        return *this;
    }

    //attempted manipulator
    static CAudit& write(CAudit& audit) { 
        //write contents of audittext to audit and clear it
        return audit; 
    }

private:
    std::stringstream audittext;
};

//to be used like
CAudit audit;
audit << "Data " << data << " received at " << time << CAudit::write;

コード内のオーバーロードされた演算子はストリームオブジェクトを返さないことを認識していますが、構文のようなマニピュレーターを使用できるかどうか疑問に思っていました。現在、コンパイラは「<<」をバイナリの右シフト演算子と見なしています。

ご入力いただきありがとうございます、パトリック

4

4 に答える 4

5

それを機能させるには、関数から関数を呼び出すよりも、関数の演算子 << のオーバーロードを追加する必要があります。

 class CAudit
 {
  //...other details here as in original question

  CAudit& operator << (CAudit & (*func)(CAudit &))
  {
        return func(*this);
  }
 };

 CAudit audit;
 audit << "some text" << CAudit::write;
于 2009-08-25T14:40:46.850 に答える
2

バイナリ シフト演算子とストリーム演算子は同じ演算子です。クラスが std::cout に "Hello world" を書き込むために operator+ をオーバーロードすることは完全に合法です (非常に悪い考えですが)。C++ 標準の作成者が、ストリームへの書き込みとしてストリームの operator<< をオーバーロードすることを決定したのと同じ方法です。
あなたはあなたの問題が何であるかを明確に書きませんでした。私の推測ではコンパイルエラーです。この場合の最善の方法は、エラー メッセージを引用することです。私が正しければ、問題は、LPCSTR に対して operator<< のみを定義し、右側で関数オブジェクトを機能させたいということです。
あなたは「マニピュレーター」という言葉を使っていますが、何か誤解しています。ストリーム (STL からのストリーム) のマニピュレーターは、書き込まれたストリームに対していくつかのアクションを実行する関数です。そして、それはこのオーバーロードのためにのみ機能します:

ostream& operator<< (ostream& ( *pf )(ostream&));

これは関数を取り、それをストリームに適用します。
同様に、次のものが必要です。

CAudit& operator<< (CAudit& ( *pf )(CAudit& audit))
{
  return (*pf)(audit);
}
于 2009-08-25T14:46:02.177 に答える
1

これじゃないかな

class CAudit
{
public:
    template< typename T >
    CAudit& operator<<( const T& data )
    {
        audittext << data;
        return *this;
    }

    class write {};

    void operator<<( const write& data )
    {
        /* whatever */
    }

private:
    std::stringstream audittext;
};

あなたがしたいことをしますか?

于 2009-08-25T14:35:55.967 に答える
1

私はトレースのために非常に似たようなことをしますが、stringstream. これにより、すべてのサードパーティoperator << ()とマニピュレータが機能することが保証されます。また、顧客の書き込みマニピュレータの代わりにデストラクターを使用します。

class DebugStream
{
public:
    DebugStream(short level, const char * file, int line) {
        sstream << "L" << level << "\t" << file << "\t" << line << "\t";
    }
    ~DebugStream() { write(sstream.str()); }

    std::ostream & stream() { return sstream; }
private:
    std::stringstream sstream;

    DebugStream(const DebugStream &);
    DebugStream & operator=(const DebugStream &);
};

これは、いくつかのマクロで利用可能になります。

#define DBG_ERROR if (1<=dbg_level()) DebugStream(1, __FILE__, __LINE__).stream()
#define DBG_INFO  if (2<=dbg_level()) DebugStream(2, __FILE__, __LINE__).stream()

そして、コードはマクロを使用するだけです

DBG_INFO << "print some debug information";

データをログ ファイルにフラッシュするために、特定の書き込みマニピュレータは必要ありません。匿名DebugStreamオブジェクトがスコープ外に出ると (制御が行を離れると)、コンテンツが自動的に書き込まれます。

この場合、通常はマクロを避けますが、ifステートメントを使用すると、実際に必要でない限り、トレース ラインを作成するオーバーヘッドがなくなります。

匿名オブジェクトは非 const 参照パラメーターとして渡すことができないためostream、メソッドを介して返すと、グローバル メンバー関数に対してこれを機能させることができます。stream()

于 2009-08-25T15:36:06.843 に答える