Adding error_info to std :: exception

I am integrating boost::exception

into existing code. Some code is now used BOOST_THROW_EXCEPTION

, but some may still throw the standard std::exception

.

I want to add error_info in catch staging site. According to the docs, if the exception is boost::exception

, I can just do this:

try {
    do_something()
}
catch( boost::exception & e ) {
    e << boost::errinfo_file_name(file_name);
    throw;
}

      

But this will only add information to boost exceptions. I want to add it to std::exception

. What's the cleanest way to do this? Here's one way, but it leads to some code duplication:

try {
    do_something()
}
catch( boost::exception & e ) {
    e << boost::errinfo_file_name(file_name);
    throw;
}
catch( std::exception & e ) {
    throw enable_error_info(e) << boost::errinfo_file_name(file_name);
}

      

Is there a method equivalent to "give me the current exception as a forcing exception, or create a forcing exception from it if there is more than one"?

EDIT : boost::enable_error_info()

This does it, but returns a copy of the original exception, which truncates part of the boost::exception

exception I was catching. Example:

int main()
{
    try {
        try {
            BOOST_THROW_EXCEPTION( std::runtime_error( "foo" ) );
        }
        catch( std::exception & e ) {
            std::cerr << e.what() << std::endl; // "foo" 
            if( const char* const* function = boost::get_error_info<boost::throw_function>(e) ) std::cerr << *function << std::endl; // "int main()"
            throw boost::enable_error_info(e) << boost::errinfo_file_name("bar");
        }
    }
    catch( std::exception & e ) {
        std::cerr << e.what() << std::endl; // "std::exception" 
        if( const char* const* function = boost::get_error_info<boost::throw_function>(e) ) std::cerr << *function << std::endl; // NOTHING
    }

    return 0;
}

      

EDIT : I tried using boost::current_exception()

and it also cuts everything off. Basically, any attempt to copy the exception will lose some data due to the cut caused by multiple inheritance. For the same reason why the docs say you should always overthrow using throw

instead throw e

. So I really don't want to take on any copying unless it's necessary.

Ideally I would like to write the following, where it current_exception_as_boost_exception()

returns a reference to the current exception if it already exists boost::exception

, otherwise it returns the result of calling boost::enable_error_info

on it.

try {
    do_something()
}
catch( std::exception & e ) {
    throw current_exception_as_boost_exception() << boost::errinfo_file_name(file_name);
}

      

Is this what it is for boost::enable_current_exception

? It is really unclear what its purpose is and it is not used in any of the tutorials.

+3


source to share


1 answer


Here is a solution that does what I want. But if it seems to me that I am inventing something here. Isn't there a built-in way to achieve the same thing?



struct rethrow
{
    rethrow()
    {
        try{ throw; }
        // Already a boost::exception
        catch( boost::exception& ) {} 
        // Something else. Make it a boost::exception
        catch( ... ) { ptr = boost::current_exception(); } 
    }

    template<class T> 
    rethrow const& operator<<( const T& t ) const
    {
        try
        {
            re();
        }
        catch( boost::exception& e )
        {
            e << t;
        }
        return *this;
    }

    ~rethrow()
    {
        re();
    }

private:
    void re() const
    {
        if( !ptr ) throw;
        else boost::rethrow_exception( ptr );
    }

    boost::exception_ptr ptr; 
};


int main()
{
    try {
        try {
            throw std::runtime_error( "foo" ); // or BOOST_THROW_EXCEPTION( std::runtime_error( "foo" ) );
        }
        catch( std::exception & e ) {
            rethrow() << boost::errinfo_file_name("bar");
        }
    }
    catch( std::exception & e ) {
        std::cerr << __LINE__ << ": caught " << e.what() << std::endl; // "caught foo"
        if( const char* const* function = boost::get_error_info<boost::throw_function>(e) ) std::cerr << __LINE__ << ": throw from " << *function << std::endl; // "throw from int main()" (when using BOOST_THROW_EXCEPTION)
        if( std::string const* fileName = boost::get_error_info<boost::errinfo_file_name>(e) ) std::cerr << __LINE__ << ": trying to open " << *fileName << std::endl; // "trying to open bar"
    }

    return 0;
}

      

+1


source







All Articles