6

テキストを一時オブジェクトとして出力しようとしている特殊なタイプの ostringstream がありますが、問題が発生しています。明確にするために、これは本質的に私がやりたいことです:

ostringstream() << "PARTY DOWN!" << endl;

「しかし、ザック、そのコードはまったく役に立たない! オブジェクトは行の最後で破棄されます。オブジェクトが何かをしたかどうかをどうやって知ることができますか?」と言う前に、私の話を聞いてください。私は単純な ostringstreams でこれを行おうとはしませんが、デストラクタが実際にデータがオブジェクトを終了するためのパスを提供する派生クラスを使用します。したがって、実際には、次のようになります。

specialstringstream() << "PARTY DOWN!" << endl;

specialstringstream には、テキストを別の場所にダンプするデストラクタがあります。

なぜこれを行うのかについては、あまり詳しく説明しません。私がしなければならないことには意味があり、既存の巨大なコードベースにうまく適合することを信じてください。

ここに問題があります。これを行うと、すべてがコンパイルおよび実行されますが、「PARTY DOWN!」の代わりにポインター アドレスが出力に出力されます。ストリング。ストリーム出力を実行するためにコンパイラによって選択された演算子が ostream& operator<< (const void* val), not であるため、これが発生していると判断しましたostream& operator<< (ostream& out, const char* s )

理由はなんとなくわかりますが、どうすればいいのか途方に暮れています。char*s を stringstream の一時的なインスタンスに出力するにはどうすればよいですか?

動作を示す SpecialStringStream オブジェクトの短いバージョンを次に示します。

class SpecialStringStream : public ostringstream
{
  public:
    SpecialStringStream(ostream* regularStream)
    {
      regularStream_ = regularStream;
    }

    ~SpecialStringStream()
    {
      if (regularStream_ != NULL)
        (*regularStream_) << str(); 
    }

  private:
    ostream* regularStream_;
};

次のようなことSpecialStringStream(someStreamPtr) << "PARTY DOWN!" << endl;をすると、メッセージの代わりに出力に「00444D60」のようなポインターアドレスが表示されます。

編集:私は自分の質問に答えるにはあまりにも新しいユーザーなので、すべての回答のおかげでここに落ち着きました。

私は、次のソリューションを思いつきました。これは、Visual C++ 8 と、必要な他のすべてのコンパイラで動作します。基本的に、const SpecialStringStream の constness を取り除き、それを ostream としてキャストし、ostream オペレーターに自分の仕事をさせるテンプレート オペレーターを作成しました。コメントでそれを細断して、私が導入したすべての恐ろしい潜在的なバグについて警告してください!

template <class T>
std::ostream& operator<<(const SpecialStringStream &o, T msg)
{
    return static_cast<std::ostream&>(const_cast<SpecialStringStream&>(o)) << msg;
}
4

4 に答える 4

4

ostream& operator<< (ostream& out, const char*)一時的に非 const 参照にバインドされないため、オーバーロードは実行できませんostream&。ローカル変数を宣言してそれを使用する以外に、(右辺値を左辺値にキャストできないため) できることはあまりありません。

{
  specialstringstream ss;
  ss << "Hello world" << std::endl; // OK, can bind to lvalue
}

考えられる解決策:右辺値参照を受け入れる別のオーバーロードを宣言できます。

std::ostream & operator<<(specialstringstream && o, const char * s)
{
  return o << s; // note: *not* "std::move(o)"
}
于 2011-11-04T18:21:09.720 に答える
2

たぶんもっと良い方法があるかもしれませんが、私は別の解決策を考え出しました:

#include <iostream>
#include <sstream>

class LogClass
{ 
    template <typename T>
    friend const LogClass& operator << (const LogClass& lc, const T& v);
public:
    LogClass()
        : str(new std::ostringstream())
        , refCount(new int(1))
    {}

    LogClass(const LogClass& other)
        : str(other.str)
    {
        ++(*refCount);
    }

    ~LogClass()
    {
        --(*refCount);
        if (!*refCount)
        {
            delete refCount;
            std::cout << str->str() << std::endl;
            delete str;
        }
    }
private:
    mutable std::ostringstream *str;
    int *refCount;

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

template <typename T>
const LogClass& operator << (const LogClass& lc, const T& v)
{
    (*lc.str) << v;
    return lc;
}

int main(int , char**)
{
    for (size_t i = 0; i < 10 ; ++i)
    {
        LogClass() << "PARTY DOWN! " << i;
    }
}

valgrind で実行する:

valgrind --tool=memcheck --leak-check=full ./LogClass

==16197== Memcheck、メモリエラー検出器

==16197== Copyright (C) 2002-2010、GNU GPL'd、Julian Seward et al.

==16197== Valgrind-3.7.0.SVN と LibVEX を使用。著作権情報については -h で再実行してください

==16197== コマンド: ./LogClass

==16197==

パーティーダウン!0

パーティーダウン!1

パーティーダウン!2

パーティーダウン!3

パーティーダウン!4

パーティーダウン!5

パーティーダウン!6

パーティーダウン!7

パーティーダウン!8

パーティーダウン!9

==16197==

==16197== ヒープ概要:

==16197== 出口で使用中: 0 ブロックで 0 バイト

==16197== 合計ヒープ使用量: 40 個の割り当て、40 個の解放、7,350 バイトの割り当て

==16197==

==16197== すべてのヒープ ブロックが解放されました -- リークの可能性はありません

==16197==

==16197== 検出され抑制されたエラーの数については、-v で再実行してください。

==16197== エラー概要: 0 コンテキストから 0 エラー (抑制: 8 から 15)

それが私が望んでいたことですが、それはスレッドセーフではありません。これを行うには、boost の shared_ptr を使用します。

于 2011-12-20T12:40:16.523 に答える
2

stringstream を実装したくありません。特別な文字列に書き込む basic_streambuf を実装したいとします。

ストリーム自体がフォーマットや同様の機能を担当します。streambufs は、最終的にデータのシンクになるものを担当します。

結局のところ、stringstream はすべて、basic_stringbuf が付加された iostream です。

于 2011-11-04T18:44:29.627 に答える