1

既存のコードの一部を調べたところ、Visual C++9とMinGWでコンパイルした場合の動作が異なることがわかりました。

inline LogMsg& LogMsg::operator<<(std::ostream& (*p_manip)(std::ostream&) )
{
    if ( p_manip == static_cast< std::ostream& (*)(std::ostream&) > ( &std::endl<char, std::char_traits<char> >) )
    {
        msg(m_output.str());
        m_output.str( "" );
    }
    else
    {
        (*p_manip) (m_output);            // or // output << p_manip;
    }
    return *this;
}

名前が示すように、これはログクラスでありoperator<<()、ストリームからendlsを削除するためにオーバーロードします。

動作が異なる理由を見つけました。テストp_manip == static_cast...はMinGWで成功しますが、Visual C++9では失敗します。

  • MinGWはキャストを「無視」し、std::endl;の実際のアドレスを返します。
  • Visual C ++ 9は、実際にはポインタをendlにキャストし、別のアドレスを返します。

テストをに変更しましたif ( p_manip == std::endl )が、期待どおりに動作するようになりました。

私の質問は:そのような複雑な(そして実際には間違った)テストの背後にある理論的根拠は何ですか?


完全を期すために:

class LogStream
{
public:
    LogStream() {}
protected:
    std::ostringstream m_output;
};

class LogMsg : public LogStream
{
    friend LogMsg& msg() ;
    static LogMsg s_stream;
public:
    LogMsg() {}
    template <typename T>
        inline LogMsg& operator<<(T p_data);
    inline LogMsg& operator<<(std::ostream& (*p_manip)(std::ostream&) );
};
4

2 に答える 2

0

推測では、元の作者はそれらが互換性のあるタイプであることに気づかず、仕様に基づいて変換を行ったと思います(コンパイラーが彼に要求することなく)。

于 2010-02-23T16:03:26.393 に答える
0

詳細については:

ステートメントif ( p_manip == std::endl )は、元のコンパイラ(gcc 3.4.5、コードが最初に開発されたコンパイラ)ではコンパイルされません。

それは、私が質問で述べたように、テストが間違っていなかったことを意味します。

于 2010-03-02T14:47:23.897 に答える