6

std::runtime_error から派生するいくつかの例外タイプを作成したいと思います。それらに stringstream タイプの機能を持たせたいと考えています。したがって、 を構成し、std::stringstreamから派生する例外クラスを作成しましたstd::runtime_error

template<typename T>
class error_stream : public std::runtime_error
{
public:
      error_stream() :
      std::runtime_error(""), ss(std::make_shared<std::basic_stringstream<T>> ())
      {
      }

      ~error_stream() throw()
      {
      }

      template <typename T>
      error_stream & operator << (const T & t)
      {
          *ss << t;
          return *this;
      }

      virtual const char * what() const throw()
      {
          get_str(s_, ss->str());
          return s_.c_str();
      }

protected:

    template <typename T>
    void get_str(std::basic_string<char> & s_, const std::basic_string<T> & str) const
    {
        s_ = str;
    }

    template<>
    void get_str(std::basic_string<char> & s_, const std::basic_string<wchar_t> & str) const
    {
        std::basic_string<char> ret(str.begin(), str.end());
        s_ = ret;
    }

protected:
    std::shared_ptr<std::basic_stringstream<T>> ss;
    mutable std::basic_string<char> s_;
};

error_streamそして、この例外から派生する、より具体的な例外タイプを作成しました。

template<typename T>
class w32file_exception : public w32utils::error_stream<T> 
{
public:
    w32file_exception() : error_stream<T>() {}
};

ただし、ここで理解できないことに遭遇しました。これは、 a をスローするw32file_exceptionと、実際にはそれを親としてしかキャッチできないためerror_streamです。誰かが私が間違っていることを見ることができますか?

    try
    {
        throw w32file_exception<char>() << "test";
    }
    catch ( w32file_exception<char> & e )
    {
        ASSERT_PASSED;
    }
    catch ( error_stream<char> & e )
    {
        std::cout << e.what() << std::endl;  // Why do I end up here?
    }
4

1 に答える 1

13

あなたは正確にどのthrowように見えますか?operator<<次のように、スローを呼び出す前に使用していますか?

throw w32file_exception<T>() << "fooobar";

答えは、 anと noをoperator<<返すため、スローされた例外のタイプは です。error_streamw32file_exceptionerror_stream

この問題は次の方法で解決できます。

template<typename T, typename DERIVED>
    class error_stream : public std::runtime_error
{
public:
    // ...
    template <typename U>
        DERIVED & operator << (const T & t)
    {
        *ss << t;
        return static_cast<DERIVED&>(*this);
    }
    // ...
};

error_streamただし、すべてのタイプの新しいタイプであるため、すべての例外をキャッチする機能が失われますDERIVED

于 2012-05-28T14:45:02.340 に答える