1

これがエラーになる理由はわかりませんが、ostringstream の内容をデバッガーにスローできるように、endl に「似た」ものを追加しようとしています。私は次のものを持っています:

class debug_stream_info
{
public:
    debug_stream_info(int errorLine, char *errorFile, int level)
        :m_errorLine(errorLine), m_errorFile(errorFile), m_logLevel(level)
    {
    }

    friend std::basic_ostringstream<char>& operator<<(std::basic_ostringstream<char>& os, debug_stream_info& debug_info);

private:
    int m_errorLine;
    std::string m_errorFile;
    int m_logLevel;

};

std::basic_ostringstream<char>& operator<<(std::basic_ostringstream<char>& os, debug_stream_info& debug_info)
{
    // Write the stream's contents to cpu_debug
    // Deleted custom logging function.  No errors here though

    // Clear the stream for re-use.
    os.str("");
    os.seekp(0);

    return os;
}

int main(int argc, char** argv)
{
    std::ostringstream myout;
    myout << "hey there" << " and some more " << "Numbers!!: " << 435 << 54.2 << " that's good for numbers" << debug_stream_info(__LINE__, __FILE__, LOG_LEVEL);

    return 0;
}

私が得ているエラーは次のとおりですerror C2679: binary '<<' : no operator found which takes a right-hand operand of type 'debug_stream_info' (or there is no acceptable conversion)。これはVS2008にあります。

私はsstream、iostreamなどを含めており、名前空間を正しく設定しています。他のエラーは発生していません。basic_ostreamすべての出現箇所をjustに置き換えてみましostringstreamたが、違いはありませんでした (w_char後でバージョンを作成しますが、単純なケースを最初に機能させたかったのです)。上記の行でオブジェクトを作成し、その行で完全に構築されたオブジェクトを渡しましたが、エラーはまったく同じでした。2 番目の引数の署名もconst変更せずに変更しました。

ここで私が間違っていることについてのアイデアはありますか?

編集:すべての応答がそこに入れたいように見えるので、 std::ostream を使用できませstd::ostringstreamstd::basic_ostringstream。その上、関数はとにかくostreamでコンパイルされません.ostreamにos.str()はないメソッドを使用しているため、サブクラスのみです。

4

3 に答える 3

8

std::ostringstreamコードの本当の問題は、ではなくオーバーロードしたことですstd::ostream。したがって、次のように記述すれば、コードは機能します。

debug_stream_info info(/** blah blah**/);

std::ostringstream oss;
oss << info ; //OK

ただし、これは機能しません。

oss << 1 << info; //ERROR

これはコンパイル エラーです。これは、式が2 番目の引数として取るオーバーロードを持たないoss<<1型のオブジェクトを返すためです。つまり、キャストを次のように使用する場合:std::ostream&debug_stream_info

static_cast<std::ostringstream&>(oss << 1) << info; //OK

その後、それは再び機能するはずです。

したがって、解決策はstd::ostreamの代わりに をオーバーロードすることですstd::basic_ostringstream

また、2 番目のパラメーターは である必要がありますconst &。これはコードの問題でもあります。

だからこれを書いてください:

std::ostream& operator<<(std::ostream&, debug_stream_info const &);
                                                        //^^^^^^^ note this

2 番目のパラメーターはconst &、一時オブジェクトをストリームに書き込めるようにする必要があります。

于 2012-04-30T16:05:59.020 に答える
1

debug_stream_info(__LINE__, __FILE__, LOG_LEVEL);何も返さない名前のないオブジェクトを作成しているため、エラー

#include <iostream>
#include <cstdio>
#include <sstream>
using namespace std;

class debug_stream_info
{
public:
    debug_stream_info(int errorLine, char *errorFile, int level)
        :m_errorLine(errorLine), m_errorFile(errorFile), m_logLevel(level)
    {
    }

    friend std::basic_ostringstream<char>& operator<<(std::basic_ostringstream<char>& os, debug_stream_info& debug_info);
    std::ostringstream& fun(std::ostringstream& os)
    {
        os<<"Ashish"<<endl;
        return os;
    }
private:
    int m_errorLine;
    std::string m_errorFile;
    int m_logLevel;

};

std::basic_ostringstream<char>& operator<<(std::basic_ostringstream<char>& os, debug_stream_info& debug_info)
{
    // Write the stream's contents to cpu_debug
    // Deleted custom logging function.  No errors here though

    // Clear the stream for re-use.
//    os.str("");
//    os.seekp(0);

    return os;
}

int main(int argc, char** argv)
{

    std::ostringstream myout, test;
        myout << "hey there" << " and some more " << "Numbers!!: " << 435 << 54.2 << " that's good for numbers"
         << debug_stream_info(1, "/home/ashish/test", 1).fun(test);
    return 0;
}
于 2012-04-30T16:11:58.183 に答える
1

Nawaz は、エラーが発生する理由を非常に明確に説明しています。この場合の通常の解決策は、 とは関係のない独自のストリーム タイプを定義することstd::istreamです。次のようなもの:

class DebugStream
{
    std::ostringstring* collector;

public:
    template <typename T>
    DebugStream& operator<<( T const& value )
    {
        if ( collector != NULL ) {
            *collector << value;
        }
        return *this;
    }
};

これには無限のバリエーションがあります。あなたの場合、型に非テンプレート メンバー関数を追加できます。おそらく、同じ引数を取るコンストラクターを追加します。

DebugStream( int lineNumber, std::string const& filename, int logLevel )
    : collector( isActive( logLevel ) ? new std::ostringstream : NULL )
{
    //  Initial insertion of lineNumber, filename, timestamp...
}

収集したデータを原子的にファイルにフラッシュする (または電子メールを送信する、システム ログに書き込むなど) デストラクタを追加することもできます。(これについては十分に注意してください。ロギングが失敗したとしても、デストラクタから例外を逃したくはありません。)

最後に、カスタム streambuf ではなく、 stringstream. 割り当てられたバッファをあるインスタンスから次のインスタンスに保持するものとしましょう。newこれを行うと、毎回ストリームを ing するのではなく、ログ レベルでインデックス付けされた (そして構成ファイルから初期化された) テーブルからインスタンスを取得できます。

于 2012-04-30T16:58:45.117 に答える