50

基本的に何もしないostreamインスタンスを作成する方法はありますか?

例えば ​​:

std::ostream dummyStream(...);
dummyStream << "Nothing will be printed";

ostringstreamを作成することもできますが、データはバッファリングされます(そして、実際にはそれらを使用して何も作成したくないので、無駄なオーバーヘッドが追加されます)。

何か案が ?

[編集]私のニーズに合ったこの関連する質問を見つけました。ただし、標準のC ++で有効な(不良ビットのない)出力ストリームを作成する方法についての回答があると便利だと思います。

4

6 に答える 6

74

カスタムstreambufが必要です。

class NullBuffer : public std::streambuf
{
public:
  int overflow(int c) { return c; }
};

その後、このバッファを任意のostreamクラスで使用できます

NullBuffer null_buffer;
std::ostream null_stream(&null_buffer);
null_stream << "Nothing will be printed";

streambuf::overflowバッファがストリームの実際の宛先にデータを出力する必要があるときに呼び出される関数です。上記のNullBufferクラスは、オーバーフローが呼び出されても何も実行しないため、それを使用するストリームは出力を生成しません。

于 2012-08-06T10:38:49.990 に答える
36

これがロギング出力を無効にする場合dummyStreamでも、引数が評価されます。ロギングが無効になっている場合の影響を最小限に抑えたい場合は、次のような条件に依存できます。

#define debugStream \
    if (debug_disabled) {} \
    else std::cerr

したがって、次のようなコードがある場合:

debugStream << "debugging output: " << foo() << std::endl;

trueの場合、引数は評価されませんdebug_disabled

于 2012-08-06T10:46:56.050 に答える
4

新しいストリームクラスの基本的なメソッドは次のとおりです。

  1. からクラスを派生させstd::streambufます;
  2. そのクラスの仮想関数をオーバーライドします。ここで実際の作業が行われます。あなたの場合、空の実装で十分です。
  3. std::ostream1つのメンバーであるstreambufクラスからクラスを派生させます。
  4. ストリームクラスのコンストラクターは、そのメンバーへのポインターをstd::ostreamのベースコンストラクターに転送する必要があります。

ただし、フォーマット手順を削除することはできません。

うまくいけば、これはあなたにいくつかのポインタを与えるでしょう。申し訳ありませんが、これを完全な答えに拡張する時間がありません。

更新:詳細については、ジョンの回答を参照してください。

于 2012-08-06T10:48:01.193 に答える
1

ログメッセージの実行時に制御可能なリダイレクトの場合、johnとSjoerdのアイデアを組み合わせた自己完結型のソリューション:

class DebugStream {
private:
    class NullStream : public std::ostream {
    private:
        class NullBuffer : public std::streambuf {
        public:
            int overflow(int c) override { return c; }
        } buffer_;
    public:
        NullStream() : std::ostream(&buffer_) {}
    } null_;

    std::ostream &output_;
    bool enabled_;

public:
    DebugStream(std::ostream &output = std::cout) : output_(output), enabled_(false) {}
    void enable(const bool enable) { enabled_ = enable; }

    template <typename T> std::ostream& operator<<(const T &arg) {
        if (enabled_) return output_ << arg;
        else return null_ << arg;
    }
};

extern DebugStream debug_stream;
#define TRACE_ENABLE(x) debug_stream.enable(x)
#define TRACELN(x) debug_stream << x << std::endl
#define TRACE(x) debug_stream << x

次に、次のようなことを行うことができます。

TRACELN("The value of x is " << x " and the value of y is " << y);

#define空のステートメントへのトレースマクロを使用して、リリースバージョンからトレースステートメントを完全に削除することも簡単です。

debug_streamただし、グローバルな場所を定義する必要があります。

于 2020-06-03T22:50:57.473 に答える
0

デバッガーのオーバーヘッドが心配な場合は、非常に単純なコードを記述して、コンパイル時にデバッグメッセージを無効にすることができます。これは私が私のc++プログラムに使用するものです。

#include <iostream>
#define DEBUGGING // Define this in your config.h or not.
#ifdef DEBUGGING
/*
 * replace std::cout with your stream , you don't need to
 * worry about the context since macros are simply search
 * and replace on compilation.
 */
#define LOG_START std::cout <<
#define LOG_REDIR <<
#define LOG_END   << std::endl;
#else
#define LOG_START if(0){(void)
#define LOG_REDIR ;(void)
#define LOG_END   ;}
#endif // DEBUGGING

int main(){
LOG_START "This is a log message " LOG_REDIR "Still a log message." LOG_END;
return 0;
}

プロジェクトを作成するときに、ユーザーがロギングを無効にするかどうかを確認します。無効にする場合は、DEBUGGINGマクロまたはチェックするように選択したマクロの定義を解除します。

これで、コードはコンパイラによって最適化されます。何かが無効になると、結果のバイナリに含まれなくなり(ほとんどの場合)、バイナリの生成が可能になります。

于 2018-07-09T02:21:53.943 に答える
-1

タイプostreamのnullストリームが必要だったので、次のようにしました。

struct NullStream: public stringstream {
   NullStream(): stringstream() {}
};

template<typename T>
void operator<<(const NullStream&, const T&) {}

アプリケーションコード:

NullStream ns;
ostream &os = ns;
os << "foo";

本当の問題は、私が継承したすべてのパブリックメソッドですが、気にしないので、それらをオーバーライドする必要はありませんでした。

于 2018-02-02T15:58:17.877 に答える