140 lines
3.1 KiB
C++
140 lines
3.1 KiB
C++
#pragma once
|
|
|
|
#include <variant>
|
|
#include <system_error>
|
|
#include <expected>
|
|
|
|
namespace ztu {
|
|
|
|
template<typename T>
|
|
using result = std::expected<T, std::error_code>;
|
|
|
|
/*
|
|
template<typename T>
|
|
class result {
|
|
static constexpr auto value_index = 0;
|
|
static constexpr auto error_index = 1;
|
|
|
|
public:
|
|
constexpr result(T value);
|
|
constexpr result(const std::error_code& error);
|
|
|
|
template<typename... Args>
|
|
void emplace(Args&&... args);
|
|
|
|
[[nodiscard]] constexpr bool ok() const;
|
|
|
|
[[nodiscard]] constexpr std::error_code error() const;
|
|
|
|
[[nodiscard]] constexpr const T& value() const;
|
|
|
|
[[nodiscard]] constexpr T& value();
|
|
|
|
[[nodiscard]] constexpr T&& value() &&;
|
|
|
|
[[nodiscard]] operator bool() const;
|
|
|
|
[[nodiscard]] const T& operator*() const;
|
|
|
|
[[nodiscard]] T& operator*();
|
|
|
|
[[nodiscard]] T&& operator*() &&;
|
|
|
|
[[nodiscard]] bool operator==(const T& rhs) const;
|
|
|
|
[[nodiscard]] bool operator==(const std::error_code& rhs) const;
|
|
|
|
template<typename Func>
|
|
auto map(Func&& func) const -> result<decltype(func(value()))>
|
|
{
|
|
if (ok()) return func(value());
|
|
return error();
|
|
}
|
|
|
|
private:
|
|
std::variant<T, std::error_code> m_data;
|
|
};
|
|
|
|
// Member function definitions
|
|
|
|
template<typename T>
|
|
constexpr result<T>::result(T value)
|
|
: m_data{ std::in_place_index_t<value_index>{}, std::move(value) }
|
|
{}
|
|
|
|
template<typename T>
|
|
constexpr result<T>::result(const std::error_code& error)
|
|
: m_data{ std::in_place_index_t<error_index>{}, error }
|
|
{}
|
|
|
|
template<typename T>
|
|
template<typename... Args>
|
|
void result<T>::emplace(Args&&... args) {
|
|
m_data.template emplace<value_index>(std::forward<Args>(args)...);
|
|
}
|
|
|
|
template<typename T>
|
|
template<typename Func>
|
|
auto result<T>::map(Func&& func) const -> result<decltype(func(value()))> {
|
|
if (ok()) return func(value());
|
|
return error();
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr bool result<T>::ok() const {
|
|
return m_data.index() == value_index;
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr std::error_code result<T>::error() const {
|
|
auto error_ptr = std::get_if<error_index>(m_data);
|
|
return error_ptr ? *error_ptr : std::error_code{};
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr const T& result<T>::value() const {
|
|
return std::get<value_index>(m_data);
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr T& result<T>::value() {
|
|
return std::get<value_index>(m_data);
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr T&& result<T>::value() && {
|
|
return std::get<value_index>(std::move(m_data));
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr result<T>::operator bool() const {
|
|
return ok();
|
|
}
|
|
|
|
template<typename T>
|
|
const T& result<T>::operator*() const {
|
|
return *std::get_if<value_index>(m_data);
|
|
}
|
|
|
|
template<typename T>
|
|
T& result<T>::operator*() {
|
|
return *std::get_if<value_index>(m_data);
|
|
}
|
|
|
|
template<typename T>
|
|
T&& result<T>::operator*() && {
|
|
return *std::get_if<value_index>(std::move(m_data));
|
|
}
|
|
|
|
template<typename T>
|
|
bool result<T>::operator==(const T& rhs) const {
|
|
return ok() and value() == rhs;
|
|
}
|
|
|
|
template<typename T>
|
|
bool result<T>::operator==(const std::error_code& rhs) const {
|
|
return not ok() and error() == rhs;
|
|
}*/
|
|
|
|
}
|