8 #ifndef Sawyer_Result_H
9 #define Sawyer_Result_H
11 #include <Sawyer/Optional.h>
13 #include <boost/lexical_cast.hpp>
14 #include <boost/serialization/access.hpp>
15 #include <boost/serialization/nvp.hpp>
16 #include <boost/serialization/split_member.hpp>
17 #include <boost/variant.hpp>
20 #include <type_traits>
24 template <
class F,
class... Args>
28 static auto test(U* p) -> decltype((*p)(std::declval<Args>()...),
void(), std::true_type());
30 static auto test(...) -> decltype(std::false_type());
32 static constexpr
bool value = decltype(test<F>(0))::value;
46 friend class boost::serialization::access;
49 void serialize(S &s,
const unsigned ) {
50 s & BOOST_SERIALIZATION_NVP(ok_);
57 explicit Ok(
const Ok &other)
61 explicit Ok(
const Value &ok)
92 using Value = std::string;
98 friend class boost::serialization::access;
101 void serialize(S &s,
const unsigned ) {
102 s & BOOST_SERIALIZATION_NVP(ok_);
108 explicit Ok(
const Value &s)
140 friend class boost::serialization::access;
143 void serialize(S &s,
const unsigned ) {
144 s & BOOST_SERIALIZATION_NVP(error_);
152 : error_(other.error_) {}
162 error_ = other.error_;
186 using Value = std::string;
192 friend class boost::serialization::access;
195 void serialize(S &s,
const unsigned ) {
196 s & BOOST_SERIALIZATION_NVP(error_);
204 : error_(other.error_) {}
214 error_ = other.error_;
235 template<
class T,
class E>
239 using ErrorValue = E;
244 boost::variant<Ok<T>,
Error<E>> result_;
247 friend class boost::serialization::access;
250 void save(S &s,
const unsigned )
const {
251 s <<boost::serialization::make_nvp(
"isOk",
isOk());
253 s <<boost::serialization::make_nvp(
"ok",
unwrap());
255 s <<boost::serialization::make_nvp(
"error",
unwrapError());
260 void load(S &s,
const unsigned ) {
262 s >>boost::serialization::make_nvp(
"isOk",
isOk);
265 s >>boost::serialization::make_nvp(
"ok",
ok);
269 s >>boost::serialization::make_nvp(
"error",
error);
274 BOOST_SERIALIZATION_SPLIT_MEMBER();
277 template<
class U = T>
281 template<
class F = E>
286 template<
class U = T>
293 template<
class F = E>
300 template<
class U = T>
302 return isOk() && *this->
ok() == *
ok;
306 template<
class U = T>
308 return !(*
this ==
ok);
312 template<
class F = E>
318 template<
class F = E>
320 return !(*
this ==
error);
324 template<
class U,
class F>
326 return ((
isOk() && other.
isOk() && *
ok() == *other.
ok()) ||
331 template<
class U,
class F>
333 return !(*
this == other);
340 return result_.which() == 0;
342 operator bool()
const {
357 return *boost::get<OkType>(result_);
370 return *boost::get<ErrorType>(result_);
377 const T&
expect(
const std::string &mesg)
const {
379 return *boost::get<OkType>(result_);
381 throw std::runtime_error(mesg);
391 return expect(
"result is not okay");
408 typename std::enable_if<is_invocable<Fn, ErrorValue>::value,
const Result>::type
423 return boost::get<OkType>(result_);
439 template<
class Exception = E>
444 throw Exception(*
error());
449 template<
class Exception = E>
463 typename std::enable_if<is_invocable<Fn, OkValue>::value,
const Result>::type
480 return boost::get<ErrorType>(result_);
489 throw std::runtime_error(mesg);
491 return *boost::get<ErrorType>(result_);
514 #if 0 // [Robb Matzke 2022-08-17]
534 Result<typename OkValue::OkValue, E> flatten()
const {
bool operator!=(const Error< F > &error) const
Test whether this result does not have the specified Error value.
const Value & operator*() const
Dereference to obtain error.
const T & expect(const std::string &mesg) const
Returns the success value or throws an exception.
Error(const Error &other)
Copy constructor.
Holds a value or nothing.
const T orElse(const T &dflt) const
Returns the contained Ok value or a provided default.
const Value * operator->() const
Dereference to obtain pointer to error.
Result & operator=(const Error< F > &error)
Assign an Error value to this result.
const T & operator*() const
Returns the success value or throws an exception.
Error(const Error &other)
Copy constructor.
const T & unwrap() const
Returns the success value or throws an exception.
Result containing a value or an error.
Ok(const Value &ok)
Construct from an value.
std::enable_if< is_invocable< Fn, ErrorValue >::value, const Result >::type orElse(Fn fn) const
Returns the contained Ok value, or calls a function.
std::enable_if< is_invocable< Fn, OkValue >::value, const Result >::type andThen(Fn fn) const
Returns the contained Error value, or calls a function.
bool operator==(const Result< U, F > &other) const
Test whether this result is equal to the other result.
Ok & operator=(const Ok &other)
Assignment.
Error & operator=(const Value &error)
Assignment.
const Result< U, E > andThen(const Result< U, E > &other) const
Returns this error or the other result.
const Value & operator*() const
Dereference to obtain value.
const Sawyer::Optional< T > ok() const
Convert to Optional<T>.
bool isError() const
Returns true if the result is an error.
const Value * operator->() const
Dereference to obtain pointer to error.
Error(const Value &error)
Construct from a value.
const Result< T, F > orElse(const Result< T, F > &other) const
Returns this value or the other result.
Error & operator=(const Value &error)
Assignment.
const Sawyer::Optional< E > error() const
Convert to Optional<E>.
Result & operator=(const Ok< U > &ok)
Assign an Ok value to this result.
bool isOk() const
Returns true if the result is okay.
bool contains(const U &value) const
Returns true if this result contains the specified okay value.
const T & orDefault() const
Returns the okay value or a default constructed value.
bool operator!=(const Result< U, F > &other) const
Test whether this result is unequal to the other result.
const Value & operator*() const
Dereference to obtain error.
bool assignTo(U &out) const
Conditionally save a value.
Name space for the entire library.
const E & unwrapError() const
Returns the error value or throws an exception.
Ok & operator=(const Value &ok)
Assignment.
const T & orThrow(const Exception &e) const
Returns the value or throws an exception constructed from the specified value.
bool operator!=(const Ok< U > &ok) const
Test whether this result does not have the specified Ok value.
Error(const E &error)
Construct from a value.
const T & orThrow() const
Returns the value or throws an exception.
Ok(const Ok &other)
Copy constructor.
bool operator==(const Ok< U > &ok) const
Test whether this result has the specified Ok value.
const E & expectError(const std::string &mesg) const
Returns the error value or throws an exception.
bool containsError(const F &error) const
Returns true if this result contains the specified error value.
Error & operator=(const Error &other)
Assignment.
bool operator==(const Error< F > &error) const
Test whether this result has the specified Error value.
Error & operator=(const Error &other)
Assignment.
const Value * operator->() const
Dereference to obtain pointer.