Skip to content

batteries/exception.hpp

batteries/exception.hpp🔗

Namespaces🔗

Name
batt
batt::detail

Classes🔗

Name
class batt::StatusException
Exception wrapper for a batt::Status value.
class batt::detail::ThrowWhenDestroyed
Temporary object that collects any optional message string parts, throwing a StatusException when destructed (unless this object has been moved).

Defines🔗

Name
BATTERIES_EXCEPTION_HPP
BATT_THROW_IF_NOT_OK(status_expr)
Expands to a statement which throws a batt::StatusException if the passed expression evaluates to a non-ok batt::StatusOr value.
BATT_OK_RESULT_OR_THROW(statusor_expr)
Expands to an expression which throws a StatusException if the passed expression evaluates to a non-ok batt::StatusOr value, and otherwise evaluates to the T value contained within the batt::StatusOr.

Macro Documentation🔗

define BATTERIES_EXCEPTION_HPP🔗

#define BATTERIES_EXCEPTION_HPP()

define BATT_THROW_IF_NOT_OK🔗

#define BATT_THROW_IF_NOT_OK(status_expr)

Expands to a statement which throws a batt::StatusException if the passed expression evaluates to a non-ok batt::StatusOr value.

This macro allows additional information to appended to the message of the exception via ostream-style insertion:

1
2
3
4
 {c++}
int arg = 7;
batt::Status status = something_that_might_fail(arg);
BATT_THROW_IF_NOT_OK(status) << "Turns out it did fail!" << BATT_INSPECT(arg);

define BATT_OK_RESULT_OR_THROW🔗

#define BATT_OK_RESULT_OR_THROW(statusor_expr)

Expands to an expression which throws a StatusException if the passed expression evaluates to a non-ok batt::StatusOr value, and otherwise evaluates to the T value contained within the batt::StatusOr.

Example:

1
2
3
4
5
6
7
 {c++}
batt::StatusOr<std::string> part1 = get_part1();
batt::StatusOr<std::string> part2 = get_part2();

// This line will throw if either part1 or part2 is not ok; otherwise it concatenates the strings.
//
std::string both_parts = BATT_OK_RESULT_OR_THROW(part1) + BATT_OK_RESULT_OR_THROW(part2);

Source code🔗

//######=###=##=#=#=#=#=#==#==#====#+==#+==============+==+==+==+=+==+=+=+=+=+=+=+
// Copyright 2024 Anthony Paul Astolfi
//
#pragma once
#ifndef BATTERIES_EXCEPTION_HPP
#define BATTERIES_EXCEPTION_HPP

#include <batteries/config.hpp>
//
#include <batteries/hint.hpp>
#include <batteries/status.hpp>
#include <batteries/stream_util.hpp>

#include <sstream>
#include <stdexcept>
#include <string_view>

namespace batt {

class StatusException : public std::runtime_error
{
   public:
    explicit StatusException(Status status, Optional<std::string_view>&& optional_message = None) noexcept;

    //+++++++++++-+-+--+----- --- -- -  -  -   -

    Status status() const noexcept;

    //+++++++++++-+-+--+----- --- -- -  -  -   -
   private:
    Status status_;
};

namespace detail {

class ThrowWhenDestroyed
{
   public:
    explicit ThrowWhenDestroyed() noexcept;

    explicit ThrowWhenDestroyed(Status status) noexcept;

    ThrowWhenDestroyed(const ThrowWhenDestroyed&) = delete;

    ThrowWhenDestroyed& operator=(const ThrowWhenDestroyed&) = delete;

    ThrowWhenDestroyed(ThrowWhenDestroyed&& that) noexcept;

    ThrowWhenDestroyed& operator=(ThrowWhenDestroyed&& that) noexcept;

    ~ThrowWhenDestroyed() noexcept(false);

    //+++++++++++-+-+--+----- --- -- -  -  -   -

    bool has_status() const noexcept;

    Status status() const noexcept;

    void cancel() noexcept;

    std::ostream& message_out() noexcept;

    template <typename T>
    ThrowWhenDestroyed& operator<<(T&& value) noexcept;

    ThrowWhenDestroyed& operator<<(std::ostream& (&fn)(std::ostream&)) noexcept;

    //+++++++++++-+-+--+----- --- -- -  -  -   -
   private:
    Optional<Status> status_;
    Optional<std::ostringstream> message_stream_;
};

}  //namespace detail

#define BATT_THROW_IF_NOT_OK(status_expr)                                                                    \
    for (auto&& BOOST_PP_CAT(BATTERIES_temp_status_result_, __LINE__) = (status_expr);                       \
         !::batt::is_ok_status(BOOST_PP_CAT(BATTERIES_temp_status_result_, __LINE__));)                      \
        ::batt::detail::ThrowWhenDestroyed                                                                   \
        {                                                                                                    \
            ::batt::to_status(BATT_FORWARD(BOOST_PP_CAT(BATTERIES_temp_status_result_, __LINE__)))           \
        }

#define BATT_OK_RESULT_OR_THROW(statusor_expr)                                                               \
    [&](auto&& statusor_value) {                                                                             \
        BATT_THROW_IF_NOT_OK(statusor_value)                                                                 \
            << "(" << BOOST_PP_STRINGIZE(statusor_expr) << ").ok() == false";                                \
        return std::move(*BATT_FORWARD(statusor_value));                                                     \
    }((statusor_expr))

//#=##=##=#==#=#==#===#+==#+==========+==+=+=+=+=+=++=+++=+++++=-++++=-+++++++++++

namespace detail {

//==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- -  -  -   -
//
template <typename T>
inline ThrowWhenDestroyed& ThrowWhenDestroyed::operator<<(T&& value) noexcept
{
    if (this->status_) {
        this->message_out() << BATT_FORWARD(value);
    }
    return *this;
}

}  //namespace detail
}  //namespace batt

#if BATT_HEADER_ONLY
#include <batteries/exception_impl.hpp>
#endif

#endif  // BATTERIES_EXCEPTION_HPP

Updated on 31 January 2025 at 21:21:05 UTC