Skip to content

Boost.Exception

Boost.Exception 库提供了一个新的异常类 boost::exception 允许给一个抛出的异常添加信息。 它被定义在文件 boost/exception/exception.hpp 中。 由于 Boost.Exception 中的类和函数分布在不同的头文件中, 下面的例子中将使用 boost/exception/all.hpp 以避免一个一个添加头文件。

cpp
#include <boost/exception/all.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/shared_array.hpp>
#include <exception>
#include <string>
#include <iostream>

// 可附加于异常中的信息。第一个参数叫做标签(tag),特定用来识别新建的数据类型。 通常是一个有特定名字的结构体。 第二个参数是与存储于异常中的tag相关的信息。
typedef boost::error_info<struct tag_errmsg, std::string> errmsg_info;
typedef boost::error_info<struct tag_handle, std::string> errmsg_handle;

class allocation_failed : public boost::exception, public std::exception
{
public:
    allocation_failed(std::size_t size)
        : what_("allocation of " + boost::lexical_cast<std::string>(size) + " bytes failed")
    {
    }

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

private:
    std::string what_;
};

boost::shared_array<char> allocate(std::size_t size)
{
    if (size > 1000)
        // Boost.Exception 提供了一个用以抛出异常的宏,它包含了函数名,以及文件名、行数的附加信息。
        BOOST_THROW_EXCEPTION(allocation_failed(size));
    return boost::shared_array<char>(new char[size]);
}

void save_configuration_data()
{
    try
    {
        boost::shared_array<char> a = allocate(2000);
        // saving configuration data ...
    }
    catch (boost::exception &e)
    {
        e << errmsg_info("saving configuration data failed");
        throw;
    }
}

void handle_eptr(std::exception_ptr eptr) // passing by value is ok
{
    if (eptr == nullptr) return;
    
    try
    {
        std::rethrow_exception(eptr);  // 重新抛出
    }
    catch (allocation_failed &e)  // 根据异常类型进行不同的处理
    {
        std::cerr << "Caught allocation_failed.\n"
                  << boost::diagnostic_information(e);
    }
    catch (boost::exception &e)
    {
        std::cerr << "Caught boost::exception.\n"
                  << boost::diagnostic_information(e);
    }
    catch (const std::logic_error &e)
    {
        std::cerr << "Caught logic_error \"" << e.what() << "\"\n";
    }
    catch (const std::exception &e)
    {
        std::cerr << "Caught exception \"" << e.what() << "\"\n";
    }
}

int main()
{
    std::exception_ptr eptr;
    try
    {
        save_configuration_data();
    }
    catch (boost::exception &e)
    {
        e << errmsg_handle("Handle by handle_eptr");
        eptr = std::current_exception(); // 获取异常指针
    }
    
    handle_eptr(eptr); // 统一异常处理
}

运行结果:

Caught allocation_failed.
/mnt/e/WorkSpace/test/boost_e.cpp(32): Throw in function boost::shared_array<char> allocate(std::size_t)
Dynamic exception type: boost::wrapexcept<allocation_failed>
std::exception::what: allocation of 2000 bytes failed
[tag_errmsg*] = saving configuration data failed
[tag_handle*] = Handle by handle_eptr

基于 VitePress 构建