2010-03-17 4 views
2

문자열 스트림을 파생 시켜서 연산자 < <을 사용하여 던져 질 메시지를 만들 수 있습니다. 이것은streambuf 또는 basic_ostringstream을 파생 하시겠습니까?

throw "some text more text 42" 

을해야

error("some text") << " more text " << 42 << std::endl; 

그래서 내가 한 것은 (어떤이 '오버 플로우'방법 과부하 (streambuf의 상속)을 errorbuf을 한 다음 ostream에를 만들 수 있습니다 : 같은 API를 보일 것이다 & errorbuf). , 당신이 당신처럼 문자열을 던져 안

class error_builder 
{ 
public: 
    error_builder(const std::string& pMsg = "") 
    { 
     mMsg << pMsg; 
    } 

    ~error_builder(void) 
    { 
     throw std::runtime_error(mMsg.str()); 
    } 

    template <typename T> 
    error_builder& operator<<(const T& pX) 
    { 
     mMsg << pX; 

     return *this; 
    } 

private: 
    std::stringstream mMsg;  
}; 


error_builder("some text") << " more text " << 42 << std::endl; 

참고 : 내가 대신 basic_ostringstream 또는 무언가를 상속 안하면 내가

답변

2

내가 다시 여기에 내가 좋아하는 매크로를 트로트 것이다. 이것은 자신의 스트림 클래스를 파생시키는 것보다 훨씬 간단하며 op < <()을 사용하여 많은 심한 합병증을 피할 수 있습니다.

+0

경우에 따라 매크로가 최상의 솔루션입니다. –

3

당신은 아마 뭔가를 수행하여 쉽게 만들 수 궁금해 ... 따라서 std::runtime_error을 사용했습니다. 모든 예외는 std::exception에서 파생되어야하며, runtime_error 인 경우 모든 의미있는 예외는 std::exception&으로 catch 될 수 있습니다.

임시 표현식이 전체 표현의 끝까지 남아 있기 때문에 효과가 있습니다.

ATHROW("Invalid value: " << x << " should be " << 42); 

예외 유형 내 자신의 라이브러리에서,하지만 난 당신이 아이디어를 얻을 생각 :

#define ATHROW(msg)            \ 
{                 \ 
    std::ostringstream os;           \ 
    os << msg;              \ 
    throw ALib::Exception(os.str(), __LINE__, __FILE__);   \ 
}                 \ 

사용에서 :

+0

정말 CONST의 char * s의를 포기하지 않습니다 ... 당신이 vasprintf이없는 경우

class CustomException : public std::exception { private: const std::string message; public: CustomException(const std::string &format, ...) { va_list args; va_start(args, format); char *formatted = 0; int len = vasprintf(&formatted, format.c_str(), args); if (len != -1) { message = std::string(formatted); free(formatted); } else { message = format; } va_end(args); } const char *what() const { return message.c_str(); } }; 

, 당신은 또한 스택에 버퍼 vsnprintf 사용할 수 있습니다 여기에

은 예입니다 . 그것은 단지 개념이었습니다. –

+0

소멸자 (http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.3)에 예외를 던져서는 안됩니다. –

+0

@Helltone : 이것은 예외입니다. 당신이 * 일반적으로 * (핵심 단어) 던져서는 안되는 이유를 이해하십시오. 두 가지 예외가 활성화되면 스택 되감기 중에 응용 프로그램이 종료됩니다. 이것은 즉시 던져지기 때문에 분명히 여기에 해당되지 않습니다. (공평하게, 시내 * 실패하고 던질 수 있었다, 그러나 meh.) 편집 : 잘, 어쨌든 그것을 고쳤다, 그래서 거기 당신은 간다. :) – GManNickG

2

GMan의 솔루션에서 일부 연산자가 누락되었습니다.

class error { 
    public: 
    explicit error(const std::string& m = "") : 
      msg(m, std::ios_base::out | std::ios_base::ate) 
    {} 

    ~error() { 
     if(!std::uncaught_exception()) { 
     throw std::runtime_error(msg.str()); 
     } 
    } 

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

    error& operator<<(std::ostream& (*t)(std::ostream&)) { 
     msg << t; 
     return *this; 
    } 
    error& operator<<(std::ios& (*t)(std::ios&)) { 
     msg << t; 
     return *this; 
    } 
    error& operator<<(std::ios_base& (*t)(std::ios_base&)) { 
     msg << t; 
     return *this; 
    } 
    private: 
    std::ostringstream msg; 
}; 
0

난 보통 내 자신의 예외 클래스를 만듭니다. what() 만 재정의해야하며 원하는만큼 많은 생성자를 제공 할 수 있습니다. 오류 메시지를 작성하려면 위와 같이 vasprintf (사용 가능한 경우) 또는 std :: ostringstream을 사용하십시오.

관련 문제