Is there any way to get some information at least for catch(…)?

前端 未结 5 594
太阳男子
太阳男子 2020-12-11 21:54

Is there any way to get at least some information inside of here?

...
catch(...)
{
  std::cerr << \"Unhandled exception\" << std::endl;
}
         


        
5条回答
  •  感动是毒
    2020-12-11 22:33

    here's an approach I used on one project. it involves rethrowing until an exception type is matched against a list of known exceptions and then dispatching some action upon a match (in this case just returning some string information, but it could also be calling a registered function object).

    This idea can be extended into a dynamic registry of exception types if you wish, the thing you have to be careful of is to ensure that the list is in most-derived to least-derived order (requires a lot of rethrowing and catching during registration!)

    #include 
    #include 
    #include 
    #include 
    #include 
    
    namespace detail {
        // a function which compares the current exception against a list of exception types terminated
        // with a void type
        // if a match is made, return the exception (mangled) class name and the what() string.
        // note that base classes will be caught if the actual class is not mentioned in the list
        // and the list must be in the order of most-derived to least derived
        //
        template
        std::string catcher_impl()
        {
            try
            {
                std::rethrow_exception(std::current_exception());
            }
            catch(const E& e)
            {
                bool is_exact = typeid(E) == typeid(e);
                return std::string(typeid(E).name()) + (is_exact ? "(exact)" : "(base class)") + " : " + e.what();
            }
            catch(...)
            {
                return catcher_impl();
            }
            return "unknown";
        }
    
        // specialise for end of list condition
        template<> std::string catcher_impl()
        {
            return "unknown exception";
        }
    }
    
    // catcher interface
    template
    std::string catcher()
    {
        return detail::catcher_impl();
    }
    
    // throw some exception type
    // and then attempt to identify it using the type list available
    //
    template
    void test(E&& ex)
    {
        try
        {
            throw std::forward(ex);
        }
        catch(...)
        {
            std::cout << "exception is: "
            << catcher()
            << std::endl;
        }
    }
    
    int main()
    {
        test(std::runtime_error("hello world"));
        test(std::logic_error("my logic error"));
        test(std::system_error(std::make_error_code(std::errc::filename_too_long)));
        test(std::invalid_argument("i don't like arguments"));
    
        struct my_runtime_error : std::runtime_error
        {
            using std::runtime_error::runtime_error;
        };
        test(my_runtime_error("an unlisted error"));
    }
    

    example output:

    exception is: St13runtime_error(exact) : hello world
    exception is: St11logic_error(exact) : my logic error
    exception is: NSt3__112system_errorE(exact) : File name too long
    exception is: St16invalid_argument(exact) : i don't like arguments
    exception is: St13runtime_error(base class) : an unlisted error
    

提交回复
热议问题