initial matador ng commit
This commit is contained in:
@@ -2,6 +2,9 @@
|
||||
#define QUERY_RESULT_HPP
|
||||
|
||||
#include <variant>
|
||||
#include <optional>
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
@@ -30,14 +33,22 @@ private:
|
||||
ValueType value_;
|
||||
};
|
||||
|
||||
template <>
|
||||
class ok<void>
|
||||
{
|
||||
public:
|
||||
using value_type = void;
|
||||
explicit constexpr ok() = default;
|
||||
};
|
||||
|
||||
template < typename ErrorType >
|
||||
class error
|
||||
class failure
|
||||
{
|
||||
public:
|
||||
using value_type = ErrorType;
|
||||
|
||||
explicit constexpr error(const ErrorType &error) : error_(error) {}
|
||||
explicit constexpr error(ErrorType &&error) : error_(std::move(error)) {}
|
||||
explicit constexpr failure(const ErrorType &error) : error_(error) {}
|
||||
explicit constexpr failure(ErrorType &&error) : error_(std::move(error)) {}
|
||||
|
||||
constexpr ErrorType&& release() { return std::move(error_); }
|
||||
const ErrorType& value() const { return error_; }
|
||||
@@ -51,51 +62,68 @@ template < typename ValueType, typename ErrorType >
|
||||
class result
|
||||
{
|
||||
public:
|
||||
using value_type = ok<ValueType>;
|
||||
using error_type = error<ErrorType>;
|
||||
using value_type = ValueType;
|
||||
using error_type = ErrorType;
|
||||
|
||||
result() : result_(ValueType{}) {}
|
||||
result(value_type value) : result_(std::move(value)) {} // NOLINT(*-explicit-constructor)
|
||||
result(error_type error) : result_(std::move(error)) {} // NOLINT(*-explicit-constructor)
|
||||
result(const result<ValueType, ErrorType> &x) = default;
|
||||
result& operator=(const result<ValueType, ErrorType> &x) = default;
|
||||
result(result<ValueType, ErrorType> &&x) = default;
|
||||
result& operator=(result<ValueType, ErrorType> &&x) = default;
|
||||
result(ok<value_type> value) : result_(std::move(value.release())) {} // NOLINT(*-explicit-constructor)
|
||||
result(failure<error_type> error) : result_(std::move(error.release())) {} // NOLINT(*-explicit-constructor)
|
||||
result(const result &x) = default;
|
||||
result& operator=(const result &x) = default;
|
||||
result(result &&x) = default;
|
||||
result& operator=(result &&x) = default;
|
||||
|
||||
operator bool() const { return is_ok(); } // NOLINT(*-explicit-constructor)
|
||||
|
||||
[[nodiscard]] bool is_ok() const { return std::holds_alternative<value_type>(result_); }
|
||||
[[nodiscard]] bool is_error() const { return std::holds_alternative<error_type>(result_); }
|
||||
|
||||
ValueType&& release() { return std::get<value_type>(result_).release(); }
|
||||
ErrorType&& release_error() { return std::get<error_type>(result_).release(); }
|
||||
ValueType&& release() { return std::move(std::get<value_type>(result_)); }
|
||||
ErrorType&& release_error() { return std::move(std::get<error_type>(result_)); }
|
||||
|
||||
const ValueType& value() const { return std::get<value_type>(result_).value(); }
|
||||
const ErrorType& err() const { return std::get<error_type>(result_).value(); }
|
||||
ErrorType err() { return std::get<error_type>(result_).value(); }
|
||||
const ValueType& value() const { return std::get<value_type>(result_); }
|
||||
ValueType& value() { return std::get<value_type>(result_); }
|
||||
const ErrorType& err() const { return std::get<error_type>(result_); }
|
||||
ErrorType err() { return std::get<error_type>(result_); }
|
||||
|
||||
constexpr const ValueType* operator->() const { return &value(); }
|
||||
constexpr ValueType* operator->() { return &std::get<value_type>(result_).value(); }
|
||||
constexpr ValueType* operator->() { return &std::get<value_type>(result_); }
|
||||
|
||||
template<typename Func, typename SecondValueType = typename std::invoke_result_t<Func, ValueType >>
|
||||
result<SecondValueType, ErrorType> transform(Func &&f) {
|
||||
constexpr const ValueType& operator*() const& noexcept { return value(); }
|
||||
constexpr ValueType& operator*() & noexcept { return value(); }
|
||||
|
||||
template<typename Func,
|
||||
typename SecondValueType = std::invoke_result_t<Func, ValueType >>
|
||||
result<SecondValueType, ErrorType> map(Func &&f) {
|
||||
if (is_ok()) {
|
||||
return result<SecondValueType, ErrorType>(ok(f(release())));
|
||||
}
|
||||
|
||||
return result<SecondValueType, ErrorType>(error(release_error()));
|
||||
return result<SecondValueType, ErrorType>(failure(release_error()));
|
||||
}
|
||||
|
||||
template<typename Func, typename SecondValueType = typename std::invoke_result_t<Func, ValueType >::value_type::value_type>
|
||||
template<typename Func,
|
||||
typename SecondErrorType = typename std::invoke_result_t<Func, ErrorType >::value_type>
|
||||
result<SecondErrorType, ErrorType> map_error(Func &&f) {
|
||||
if (!is_ok()) {
|
||||
return result<SecondErrorType, ErrorType>(ok(release()));
|
||||
}
|
||||
|
||||
return result<SecondErrorType, ErrorType>(error(release_error()));
|
||||
}
|
||||
|
||||
template<typename Func,
|
||||
typename SecondValueType = typename std::invoke_result_t<Func, ValueType>::value_type>
|
||||
result<SecondValueType, ErrorType> and_then(Func &&f) {
|
||||
if (is_ok()) {
|
||||
return f(release());
|
||||
}
|
||||
|
||||
return result<SecondValueType, ErrorType>(error(release_error()));
|
||||
return result<SecondValueType, ErrorType>(failure(release_error()));
|
||||
}
|
||||
|
||||
template<typename Func, typename SecondErrorType = typename std::invoke_result_t<Func, ErrorType >::error_type::value_type>
|
||||
template<typename Func,
|
||||
typename SecondErrorType = typename std::invoke_result_t<Func, ErrorType >::value_type>
|
||||
result<ValueType, SecondErrorType> or_else(Func &&f) {
|
||||
if (is_error()) {
|
||||
return f(err());
|
||||
@@ -108,6 +136,62 @@ private:
|
||||
std::variant<value_type, error_type> result_;
|
||||
};
|
||||
|
||||
template < typename ErrorType >
|
||||
class result<void, ErrorType>
|
||||
{
|
||||
public:
|
||||
using value_type = void;
|
||||
using error_type = ErrorType;
|
||||
|
||||
result() = default;
|
||||
result(ok<void> /*value*/) {}
|
||||
result(failure<error_type> error) : result_(std::move(error.release())) {} // NOLINT(*-explicit-constructor)
|
||||
result(const result &x) = default;
|
||||
result& operator=(const result &x) = default;
|
||||
result(result &&x) = default;
|
||||
result& operator=(result &&x) = default;
|
||||
|
||||
operator bool() const { return is_ok(); } // NOLINT(*-explicit-constructor)
|
||||
|
||||
[[nodiscard]] bool is_ok() const { return !result_.has_value(); }
|
||||
[[nodiscard]] bool is_error() const { return result_.has_value(); }
|
||||
|
||||
ErrorType&& release_error() { return result_->release(); }
|
||||
|
||||
const ErrorType& err() const { return result_.value(); }
|
||||
ErrorType err() { return result_.value(); }
|
||||
|
||||
template<typename Func, typename SecondValueType = std::invoke_result_t<Func>>
|
||||
result<SecondValueType, ErrorType> map(Func &&f) {
|
||||
if (is_ok()) {
|
||||
return result<SecondValueType, ErrorType>(ok(f()));
|
||||
}
|
||||
|
||||
return result<SecondValueType, ErrorType>(error(release_error()));
|
||||
}
|
||||
|
||||
template<typename Func>
|
||||
result and_then(Func &&f) {
|
||||
if (is_ok()) {
|
||||
return f();
|
||||
}
|
||||
|
||||
return result(error(release_error()));
|
||||
}
|
||||
|
||||
template<typename Func, typename SecondErrorType = typename std::invoke_result_t<Func, ErrorType >::value_type>
|
||||
result<void, SecondErrorType> or_else(Func &&f) {
|
||||
if (is_error()) {
|
||||
return f(err());
|
||||
}
|
||||
|
||||
return result<void, SecondErrorType>(ok<void>());
|
||||
}
|
||||
|
||||
private:
|
||||
std::optional<error_type> result_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //QUERY_RESULT_HPP
|
||||
|
||||
Reference in New Issue
Block a user