Program Listing for File expected_helpers.h

Return to documentation for file (utils/expected_helpers.h)

#pragma once

#include <expected.h>

#include <concepts>

template <typename T>
concept OptionalOrExpectedCompatible = requires(T obj) {
    { obj.has_value() } -> std::same_as<bool>;
    { static_cast<bool>(obj) };
    { *obj };
};

#define UNWRAP_OR_RETURN_AND_LOG(operation)                                                       \
    ({                                                                                        \
        tl::expected _result = (operation);                                               \
        if (!_result) {                                                                   \
            spdlog::error("at {} in {}:{} {} returned error", __FUNCTION__, __FILE__, \
                __LINE__, #operation);                                                \
            return tl::unexpected(_result.error());                                   \
        }                                                                                 \
        std::move(*_result);                                                              \
    })

#define UNWRAP_OR_RETURN_VAL_AND_LOG(operation, val)                                              \
    ({                                                                                        \
        auto _result = (operation);                                                       \
        static_assert(OptionalOrExpectedCompatible<decltype(_result)>);                   \
        if (!_result) {                                                                   \
            spdlog::error("at {} in {}:{} {} returned error", __FUNCTION__, __FILE__, \
                __LINE__, #operation);                                                \
            return val;                                                               \
        }                                                                                 \
        std::move(*_result);                                                              \
    })

#define UNWRAP_OR_RETURN_ERR_AND_LOG(operation, val)                                              \
    ({                                                                                        \
        auto _result = (operation);                                                       \
        static_assert(OptionalOrExpectedCompatible<decltype(_result)>);                   \
        if (!_result) {                                                                   \
            spdlog::error("at {} in {}:{} {} returned error", __FUNCTION__, __FILE__, \
                __LINE__, #operation);                                                \
            return tl::unexpected(val);                                               \
        }                                                                                 \
        std::move(*_result);                                                              \
    })

#ifdef EXPECTED_HELPERS_ALWAYS_LOG
#define UNWRAP_OR_RETURN_ERR UNWRAP_OR_RETURN_ERR_AND_LOG
#define UNWRAP_OR_RETURN_VAL UNWRAP_OR_RETURN_VAL_AND_LOG
#define UNWRAP_OR_RETURN UNWRAP_OR_RETURN_AND_LOG
#else
#define UNWRAP_OR_RETURN(operation)                             \
    ({                                                      \
        tl::expected _result = (operation);             \
        if (!_result)                                   \
            return tl::unexpected(_result.error()); \
        std::move(*_result);                            \
    })

#define UNWRAP_OR_RETURN_RAW(operation)             \
    ({                                          \
        tl::expected _result = (operation); \
        if (!_result)                       \
            return _result.error();     \
        std::move(*_result);                \
    })

#define UNWRAP_OR_RETURN_VAL(operation, val)                                    \
    ({                                                                      \
        auto _result = (operation);                                     \
        static_assert(OptionalOrExpectedCompatible<decltype(_result)>); \
        if (!_result)                                                   \
            return val;                                             \
        std::move(*_result);                                            \
    })

#define UNWRAP_OR_RETURN_ERR(operation, err)                                    \
    ({                                                                      \
        auto _result = (operation);                                     \
        static_assert(OptionalOrExpectedCompatible<decltype(_result)>); \
        if (!_result)                                                   \
            return tl::unexpected(err);                             \
        std::move(*_result);                                            \
    })
#endif