2015-02-05 2 views
4

현재 Scott Meyers의 Effective C++라는 책을 읽었습니다. 함수와 비슷한 매크로에 대해 #define 이상의 함수를 inline보다 선호해야한다고 말합니다.내 C++ 예외 매크로를 __LINE__ 및 __FILE__ 지원 인라인 함수로 바꿀 수 있습니까?

이제 예외 매크로를 바꾸기 위해 인라인 함수를 코딩하려고합니다. 이런 내 오랜 매크로 외모 :

inline void __EXCEPTION(const std::string aMessage) 
{ 
    std::ostringstream stream; 
    stream << "EXCEPTION: " << aMessage << ", file " <<__FILE__ << " line " << __LINE__; 
    throw ExceptionImpl(stream.str()); 
} 

으로 아마 어떤 사람들은 이미 그들이 항상 참조하기 때문에 지금 __FILE____LINE__ 매크로, 쓸모없는, 기대 :

#define __EXCEPTION(aMessage) \ 
{ \ 
    std::ostringstream stream; \ 
    stream << "EXCEPTION: " << aMessage << ", file " <<__FILE__ << " line " << __LINE__; \ 
    throw ExceptionImpl(stream.str()); \ 
} 

나의 새로운 인라인 기능이 있습니다 C++ - 인라인 함수 정의 파일.

이 동작을 피하는 방법이 있습니까? 아니면 이전 매크로를 사용해야합니까? 여기이 스레드를 읽고, 나는 아마 이미 잘 작동하는 나의 두 번째 예제의 방법이 없다고 생각한다 :

+1

두 번째 매크로는 아니므로 소개가 정확하지 않습니다. 때로는 매크로가 * 일을 처리하는 방법입니다 (예 : this). – WhozCraig

+0

@WhozCraig 힌트를 보내 주셔서 감사합니다. – John

답변

16

사용하지 마십시오 __ (이중 밑줄) 예약 된대로. inline 기능을 갖는 것이 좋습니다.

#define MY_EXCEPTION(aMessage) MyException(aMessage, __FILE__, __LINE__) 

inline void MyException(const std::string aMessage, 
         const char* fileName, 
         const std::size_t lineNumber) 
{ 
    std::ostringstream stream; 
    stream << "EXCEPTION: " << aMessage << ", file " << fileName << " line " << lineNumber; 
    throw ExceptionImpl(stream.str()); 
} 
3

inline 비교하여 귀하의 경우에 #define 기능과 같은 매크로를 사용의 또 다른 차이점이 있음을 고려하시기 바랍니다 :
그러나, 여기 당신이 매크로의 혼합과 기능을 필요, 따라서 당신은 다음과 같은 작업을 수행 할 수 기능. 당신은 매크로의 호출 연산자 및 매개 변수를 스트리밍 사용되는 메시지의 텍스트로 구성 될 수 있었다 : 나는 이런 식으로 뭔가가 필요했습니다

__EXCEPTION("My message with a value " << val) 

그러나 대부분의 시간을, 그것은 주장처럼 (특정 조건을 확인하는 것이 었습니다). 값도 인쇄되어 좀 더 전문

#define MY_EXCEPTION_COND(cond)     \ 
    if (bool(cond) == false)      \ 
    {            \ 
     std::string _s(#cond " == false");  \ 
     MyException(_s, __FILE__, __LINE__);  \ 
    } 

또는 뭔가 : 그래서 당신은 같은과 @의 iammilind의 예를 확장 할 수

template <typename T> 
inline void MyExceptionValueCompare(const T&   a, 
            const T&   b, 
            const char*  fileName, 
            const std::size_t lineNumber) 
{ 
    if (a != b) 
    { 
     std::ostringstream stream; 
     stream << "EXCEPTION: " << a << " != " << b << ", file " << fileName << " line " << lineNumber; 
     throw ExceptionImpl(stream.str()); 
    } 
} 

#define MY_EXCEPTION_COMP(a, b) MyExceptionValueCompare(a, b, __FILE__, __LINE__) 

당신이보고 싶을 수있는 또 다른 방법은 마이크로 소프트의입니다 Microsoft::VisualStudio::CppUnitTestFramework 네임 스페이스 (VC \ UnitTest \ Include \ CppUnitTestAssert.h)에서 __LineInfo 클래스의 사용. https://msdn.microsoft.com/en-us/library/hh694604.aspx

3

이 매크로가 오래된 매크로라는 것을 알았지 만 예외 매크로에서 라인을 인쇄하는 방법은 근본적으로 결함이 있으며 더 나은 대안이 있다고 생각합니다. 나는 매크로가 다음 코드와 유사 사용된다는 가정이 방법으로

try { 
    /// code 
    throw; 
} 
catch (...) { __EXCEPTION(aMessage); } 

매크로 인쇄를 제외하고 catch'ed 된 위치. 그러나 문제 해결 및 디버깅을 위해 throw'n이었습니다.

해당 정보를 얻으려면 __FILE____LINE__ 매크로를 예외에 첨부 할 수 있습니다. 그러나, 우리는 여전히 매크로 완전히 제거 얻을 수 없다, 그러나 우리는 적어도 정확한 던져 위치 얻을 :

#include <iostream> 
#include <exception> 
#include <string> 

#define MY_THROW(msg) throw my_error(__FILE__, __LINE__, msg) 

struct my_error : std::exception 
{ 
    my_error(const std::string & f, int l, const std::string & m) 
     : file(f) 
     , line(l) 
     , message(m) 
    {} 
    std::string file; 
    int line; 
    std::string message; 

    char const * what() const throw() { return message.c_str(); } 
}; 

void my_exceptionhandler() 
{ 
    try { 
     throw; // re-throw the exception and capture the correct type 
    } 
    catch (my_error & e) 
    { 
     std::cout << "Exception: " << e.what() << " in line: " << e.line << std::endl; 
    } 
} 

int main() 
{ 
    try { 

     MY_THROW("error1"); 

    } catch(...) { my_exceptionhandler(); } 
} 

은 우리가 boost::exception를 사용하고자하는 경우 하나 개의 추가 개선 할 수있다 : 우리는 매크로를 제거 할 수 있습니다 최소한 우리 자신의 코드에서 한정사. 전체 프로그램이 짧아지고 코드 실행 및 오류 처리 위치가 잘 분리 될 수 있습니다.

#include <iostream> 
#include <boost/exception/all.hpp> 

typedef boost::error_info<struct tag_error_msg, std::string> error_message; 
struct error : virtual std::exception, virtual boost::exception { }; 
struct my_error:   virtual error { }; 

void my_exceptionhandler() 
{ 
    using boost::get_error_info; 

    try { 
     throw; 
    } 
    catch(boost::exception & e) 
    { 
     char const * const * file = get_error_info<boost::throw_file>(e); 
     int const * line = get_error_info<boost::throw_line>(e); 
     char const * const * throw_func = get_error_info<boost::throw_function>(e); 
     std::cout << diagnostic_information(e, false) 
        << " in File: " << *file << "(" << *line << ")" 
        " in Function: " << *throw_func; 
    } 
} 

int main() 
{ 
    try { 

     BOOST_THROW_EXCEPTION(my_error() << error_message("Test error")); 

    } catch(...) { my_exceptionhandler(); } 
}