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_);
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 inline Ok<std::string>
makeOk(
const char *s) {
141 return Ok<std::string>(std::string(s));
143 inline Ok<std::string>
makeOk(
char *s) {
144 return Ok<std::string>(std::string(s));
157 friend class boost::serialization::access;
160 void serialize(S &s,
const unsigned ) {
161 s & BOOST_SERIALIZATION_NVP(error_);
169 : error_(other.error_) {}
179 error_ = other.error_;
203 using Value = std::string;
209 friend class boost::serialization::access;
212 void serialize(S &s,
const unsigned ) {
213 s & BOOST_SERIALIZATION_NVP(error_);
221 : error_(other.error_) {}
231 error_ = other.error_;
261 inline Error<std::string>
makeError(
const char *s) {
262 return Error<std::string>(std::string(s));
264 inline Error<std::string>
makeError(
char *s) {
265 return Error<std::string>(std::string(s));
269 template<
class T,
class E>
273 using ErrorValue = E;
278 boost::variant<Ok<T>,
Error<E>> result_;
281 friend class boost::serialization::access;
284 void save(S &s,
const unsigned )
const {
285 s <<boost::serialization::make_nvp(
"isOk",
isOk());
287 s <<boost::serialization::make_nvp(
"ok",
unwrap());
289 s <<boost::serialization::make_nvp(
"error",
unwrapError());
294 void load(S &s,
const unsigned ) {
296 s >>boost::serialization::make_nvp(
"isOk", isOk);
299 s >>boost::serialization::make_nvp(
"ok", ok);
303 s >>boost::serialization::make_nvp(
"error", error);
308 BOOST_SERIALIZATION_SPLIT_MEMBER();
311 template<
class U = T>
315 template<
class F = E>
320 template<
class U = T>
327 template<
class F = E>
334 template<
class U = T>
336 return isOk() && *this->
ok() == *
ok;
340 template<
class U = T>
342 return !(*
this ==
ok);
346 template<
class F = E>
352 template<
class F = E>
354 return !(*
this ==
error);
358 template<
class U,
class F>
360 return ((
isOk() && other.
isOk() && *
ok() == *other.
ok()) ||
365 template<
class U,
class F>
367 return !(*
this == other);
374 return result_.which() == 0;
376 explicit operator bool()
const {
391 return *boost::get<OkType>(result_);
404 return *boost::get<ErrorType>(result_);
411 const T&
expect(
const std::string &mesg)
const {
413 return *boost::get<OkType>(result_);
415 throw std::runtime_error(mesg);
425 return expect(
"result is not okay");
442 typename std::enable_if<is_invocable<Fn, ErrorValue>::value,
const Result>::type
457 return boost::get<OkType>(result_);
473 template<
class Exception = E>
478 throw Exception(*
error());
483 template<
class Exception = E>
497 typename std::enable_if<is_invocable<Fn, OkValue>::value,
const Result>::type
514 return boost::get<ErrorType>(result_);
523 throw std::runtime_error(mesg);
525 return *boost::get<ErrorType>(result_);
548 #if 0 // [Robb Matzke 2022-08-17]
568 Result<typename OkValue::OkValue, E> flatten()
const {
Error(const E &error)
Construct from a value.
bool operator!=(const Result< U, F > &other) const
Test whether this result is unequal to the other result.
const T & expect(const std::string &mesg) const
Returns the success value or throws an exception.
const Value * operator->() const
Dereference to obtain pointer to error.
const T & orDefault() const
Returns the okay value or a default constructed value.
const T & orThrow() const
Returns the value or throws an exception.
const Value & operator*() const
Dereference to obtain value.
Result & operator=(const Ok< U > &ok)
Assign an Ok value to this result.
Ok< T > makeOk(const T &value)
Conventient way to constructo an Ok value before C++17.
Error(const Value &error)
Construct from a value.
const Sawyer::Optional< T > ok() const
Convert to Optional.
Holds a value or nothing.
Error< T > makeError(const T &value)
Conventient way to constructo an Error value before C++17.
Error & operator=(const Error &other)
Assignment.
Result containing a value or an error.
const Result< T, F > orElse(const Result< T, F > &other) const
Returns this value or the other result.
bool operator!=(const Ok< U > &ok) const
Test whether this result does not have the specified Ok value.
const Value * operator->() const
Dereference to obtain pointer to error.
bool containsError(const F &error) const
Returns true if this result contains the specified error value.
Name space for the entire library.
bool assignTo(U &out) const
Conditionally save a value.
const E & unwrapError() const
Returns the error value or throws an exception.
Error & operator=(const Value &error)
Assignment.
bool isError() const
Returns true if the result is an error.
Error(const Error &other)
Copy constructor.
Error & operator=(const Error &other)
Assignment.
std::enable_if< is_invocable< Fn, ErrorValue >::value, const Result >::type orElse(Fn fn) const
Returns the contained Ok value, or calls a function.
const T & operator*() const
Returns the success value or throws an exception.
bool isOk() const
Returns true if the result is okay.
const T orElse(const T &dflt) const
Returns the contained Ok value or a provided default.
Ok(const Ok &other)
Copy constructor.
Ok & operator=(const Value &ok)
Assignment.
bool contains(const U &value) const
Returns true if this result contains the specified okay value.
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.
bool operator==(const Result< U, F > &other) const
Test whether this result is equal to the other result.
Ok & operator=(const Ok &other)
Assignment.
std::enable_if< is_invocable< Fn, OkValue >::value, const Result >::type andThen(Fn fn) const
Returns the contained Error value, or calls a function.
const Sawyer::Optional< E > error() const
Convert to Optional.
Result & operator=(const Error< F > &error)
Assign an Error value to this result.
const E & expectError(const std::string &mesg) const
Returns the error value or throws an exception.
Error & operator=(const Value &error)
Assignment.
Error(const Error &other)
Copy constructor.
const T & unwrap() const
Returns the success value or throws an exception.
bool operator==(const Ok< U > &ok) const
Test whether this result has the specified Ok value.
const T & orThrow(const Exception &e) const
Returns the value or throws an exception constructed from the specified value.
const Value & operator*() const
Dereference to obtain error.
const Result< U, E > andThen(const Result< U, E > &other) const
Returns this error or the other result.
Ok(const Value &ok)
Construct from an value.
bool operator==(const Error< F > &error) const
Test whether this result has the specified Error value.
const Value * operator->() const
Dereference to obtain pointer.