FlatImage
A configurable Linux containerization system
Loading...
Searching...
No Matches
/flatimage/src/std/expected.hpp

Get value or default-constructed T.

Get value or default-constructed T

Returns
T The contained value if present, otherwise T{} @requires T must be default constructible
Value<int> result = get_value();
int value = result.or_default(); // Returns 0 if error
Enhanced expected type with integrated logging capabilities.
Definition expected.hpp:44
#pragma once
#include <expected>
#include <string>
#include <array>
#include <type_traits>
#include "string.hpp"
#include "../lib/log.hpp"
template<typename T, typename E = std::string>
struct Value : std::expected<T, E>
{
using std::expected<T, E>::expected;
private:
constexpr static std::array<const char[6], 5> const m_prefix{"D::{}", "I::{}", "W::{}", "E::{}", "C::{}"};
template<ns_string::static_string fmt>
constexpr static int select_prefix()
{
constexpr std::string_view sv{fmt.data};
return sv.starts_with("D")? 0
: sv.starts_with("I")? 1
: sv.starts_with("W")? 2
: sv.starts_with("E")? 3
: 4;
}
public:
template<ns_string::static_string fmt = "Q::", typename... Args>
void discard_impl(ns_log::Location const& loc, Args&&... args)
{
if (not this->has_value())
{
logger_loc(loc, m_prefix[select_prefix<fmt>()], this->error());
logger_loc(loc, fmt.data, std::forward<Args>(args)...);
}
}
template<ns_string::static_string fmt = "Q::", typename... Args>
Value<T,E> forward_impl(ns_log::Location const& loc, Args&&... args)
{
if (not this->has_value())
{
logger_loc(loc, m_prefix[select_prefix<fmt>()], this->error());
logger_loc(loc, fmt.data, std::forward<Args>(args)...);
return std::unexpected(this->error());
}
return Value<T,E>(std::move(this->value()));
}
T or_default() requires std::default_initializable<T>
{
if (!this->has_value()) {
return T{};
}
return std::move(**this);
}
};
constexpr auto __expected_fn = [](auto&& e) { return e; };
#define NOPT(expr, ...) NOPT_IDENTITY(__VA_OPT__(NOPT_EAT) (expr))
#define NOPT_IDENTITY(...) __VA_ARGS__
#define NOPT_EAT(...)
#define Pop(expr, ...) \
({ \
auto __expected_ret = (expr); \
if (!__expected_ret) \
{ \
std::string error = std::move(__expected_ret).error(); \
/* Log expected error at DEBUG level */ \
logger("D::{}", error); \
/* If a custom error was provided, log and propagate it instead */ \
__VA_OPT__( \
logger(__VA_ARGS__); \
error = [&](auto &&fmt, auto &&...args) \
{ \
if constexpr (sizeof...(args) > 0) \
{ \
return ns_log::vformat(std::string_view(fmt).substr(3), \
ns_string::to_string(args)...); \
} \
else \
{ \
return std::string_view(fmt).substr(3); \
} \
}(__VA_ARGS__); \
) \
return __expected_fn(std::unexpected(error)); \
} \
std::move(__expected_ret).value(); \
})
#define discard(fmt,...) discard_impl<fmt>(ns_log::Location() __VA_OPT__(,) __VA_ARGS__)
#define forward(fmt,...) forward_impl<fmt>(ns_log::Location() __VA_OPT__(,) __VA_ARGS__)
template<typename Fn>
and (not ns_concept::IsInstanceOf<std::invoke_result_t<Fn>, std::expected>)
{
try
{
if constexpr (std::is_void_v<std::invoke_result_t<Fn>>)
{
f();
return {};
}
else
{
return f();
}
}
catch (std::exception const& e)
{
return std::unexpected(e.what());
}
catch (...)
{
return std::unexpected("Unknown exception was thrown");
}
}
#define Try(expr,...) Pop(__except_impl([&]{ return (expr); }), __VA_ARGS__)
#define Catch(expr, ...) (__except_impl([&]{ return (expr); })__VA_OPT__(.template forward(__VA_ARGS__)))
#define Error(fmt,...) \
({ \
logger(fmt __VA_OPT__(,) __VA_ARGS__); \
[&](auto&&... __fmt_args) \
{ \
if constexpr (sizeof...(__fmt_args) > 0) \
{ \
return std::unexpected( \
std::format(std::string_view(fmt).substr(3) \
, ns_string::to_string(__fmt_args)...) \
); \
} \
else \
{ \
return std::unexpected( \
std::format(std::string_view(fmt).substr(3)) \
); \
} \
}(__VA_ARGS__); \
})
Concept to check if a type is an instance of a specific template.
Definition concept.hpp:72
constexpr auto __expected_fn
Lambda helper for Pop macro error returns.
Definition expected.hpp:147
auto __except_impl(Fn &&f) -> Value< std::invoke_result_t< Fn > >
Convert exceptions to Value errors.
Definition expected.hpp:254
#define logger_loc(loc, fmt,...)
Compile-time log level dispatch macro with manual location specification.
Definition log.hpp:727
String helpers.
void discard_impl(ns_log::Location const &loc, Args &&... args)
Log error and discard it if present.
Definition expected.hpp:87
Value< T, E > forward_impl(ns_log::Location const &loc, Args &&... args)
Forward error with logging or return value.
Definition expected.hpp:111
Source code location information for log messages.
Definition log.hpp:403
Compile-time string container with fixed size.
Definition string.hpp:35