C++ approach to handling a collection of multiple exceptions?

520 views Asked by At

In C++17, what is the proper pattern/approach to handling a collection of multiple exceptions?

Is there a C++ equivalent to C# AggregateException Class?

(I'm aware that exception as flow control is an anti-pattern.)

2

There are 2 answers

0
darune On BEST ANSWER

This is not common problem I see in c++. If you plan to use a library for multithread/multicore processing, you might wan't to check out what that library offers or how exceptions are handled. If you just need that sort of capability yourself you can do something like the following (pseudocode):

struct AggregateExcpetions {
  std::vector< std::variant< exception_type_1, exception_type_2, exception_type_3 > > m_exceptions;
}

Instead of using a variant it might be easier to just use a common base class - for example std::exception or perhaps std::runtime_error.

struct AggregateExcpetions {
  std::vector< std::unique_ptr<std::exception> > m_exceptions;
}
0
Kliment Nechaev On

As far as I'm concerned, there is no similar exception in C++.

You can write one by yourself.

I am using this one for saving errors on retrying operations.

When retrying operation exceeds its retry count, I aggregate exceptions into AggregateException and throw it.

    class AggregateException : public std::exception
    {
    public:
        explicit AggregateException(std::vector<std::exception> exceptions)
        {
            _exceptions = std::move(exceptions);

            std::stringstream whatString;
            whatString << "AggregateException:" << std::endl;
            for (auto const& ex : _exceptions){
                whatString << ex.what() << std::endl;
            }
            _whatMessage = whatString.str();
        }


        [[nodiscard]]
        const char* what() const noexcept override {
            return _whatMessage.c_str();
        }
    private:
        std::vector<std::exception> _exceptions;
        std::string _whatMessage;
    };

Usage example:

    std::vector<std::exception> exceptions;
    try
    {
        throw std::runtime_error("foo");
    } catch (const std::exception& ex){
        exceptions.emplace_back(ex);
    }
    try
    {
        throw std::runtime_error("bar");
    } catch (const std::exception& ex){
        exceptions.emplace_back(ex);
    }

    try
    {
        throw k_crm::AggregateException(exceptions);
    } catch (const std::exception& ex){
        std::cout << ex.what() << std::endl;
    }

Prints out:

AggregateException:
foo
bar