11#include <Sawyer/Optional.h>
13#include <boost/lexical_cast.hpp>
14#include <boost/variant.hpp>
21template <
class F,
class... Args>
25 static auto test(U* p) ->
decltype((*p)(std::declval<Args>()...), void(), std::true_type());
27 static auto test(...) ->
decltype(std::false_type());
29 static constexpr bool value =
decltype(test<F>(0))::value;
42#ifdef SAWYER_HAVE_BOOST_SERIALIZATION
44 friend class boost::serialization::access;
47 void serialize(S &s,
const unsigned ) {
48 s & BOOST_SERIALIZATION_NVP(ok_);
52#ifdef SAWYER_HAVE_CEREAL
54 friend class cereal::access;
56 template<
class Archive>
57 void CEREAL_SERIALIZE_FUNCTION_NAME(Archive &archive) {
58 archive(cereal::make_nvp(
"ok", ok_));
70 explicit Ok(
const Value &ok)
101 using Value = std::string;
106#ifdef SAWYER_HAVE_BOOST_SERIALIZATION
108 friend class boost::serialization::access;
111 void serialize(S &s,
const unsigned ) {
112 s & BOOST_SERIALIZATION_NVP(ok_);
116#ifdef SAWYER_HAVE_CEREAL
118 friend class cereal::access;
120 template<
class Archive>
121 void CEREAL_SERIALIZE_FUNCTION_NAME(Archive &archive) {
122 archive(cereal::make_nvp(
"ok", ok_));
129 explicit Ok(
const Value &s)
161inline Ok<std::string>
makeOk(
const char *s) {
162 return Ok<std::string>(std::string(s));
164inline Ok<std::string>
makeOk(
char *s) {
165 return Ok<std::string>(std::string(s));
177#ifdef SAWYER_HAVE_BOOST_SERIALIZATION
179 friend class boost::serialization::access;
182 void serialize(S &s,
const unsigned ) {
183 s & BOOST_SERIALIZATION_NVP(error_);
187#ifdef SAWYER_HAVE_CEREAL
189 friend class cereal::access;
191 template<
class Archive>
192 void CEREAL_SERIALIZE_FUNCTION_NAME(Archive &archive) {
193 archive(cereal::make_nvp(
"error", error_));
202 : error_(other.error_) {}
212 error_ = other.error_;
236 using Value = std::string;
241#ifdef SAWYER_HAVE_BOOST_SERIALIZATION
243 friend class boost::serialization::access;
246 void serialize(S &s,
const unsigned ) {
247 s & BOOST_SERIALIZATION_NVP(error_);
251#ifdef SAWYER_HAVE_CEREAL
253 friend class cereal::access;
255 template<
class Archive>
256 void CEREAL_SERIALIZE_FUNCTION_NAME(Archive &archive) {
257 archive(cereal::make_nvp(
"error", error_));
266 : error_(other.error_) {}
276 error_ = other.error_;
306inline Error<std::string>
makeError(
const char *s) {
307 return Error<std::string>(std::string(s));
309inline Error<std::string>
makeError(
char *s) {
310 return Error<std::string>(std::string(s));
314template<
class T,
class E>
318 using ErrorValue = E;
323 boost::variant<Ok<T>,
Error<E>> result_;
325#ifdef SAWYER_HAVE_BOOST_SERIALIZATION
327 friend class boost::serialization::access;
330 void save(S &s,
const unsigned )
const {
331 s <<boost::serialization::make_nvp(
"isOk",
isOk());
333 s <<boost::serialization::make_nvp(
"ok",
unwrap());
335 s <<boost::serialization::make_nvp(
"error",
unwrapError());
340 void load(S &s,
const unsigned ) {
342 s >>boost::serialization::make_nvp(
"isOk",
isOk);
345 s >>boost::serialization::make_nvp(
"ok",
ok);
349 s >>boost::serialization::make_nvp(
"error",
error);
354 BOOST_SERIALIZATION_SPLIT_MEMBER();
357#ifdef SAWYER_HAVE_CEREAL
359 friend class cereal::access;
361 template<
class Archive>
362 void CEREAL_SAVE_FUNCTION_NAME(Archive &archive)
const {
363 archive(cereal::make_nvp(
"isOk",
isOk()));
365 archive(cereal::make_nvp(
"ok",
unwrap()));
371 template<
class Archive>
372 void CEREAL_LOAD_FUNCTION_NAME(Archive &archive) {
374 archive(cereal::make_nvp(
"isOk",
isOk));
377 archive(cereal::make_nvp(
"ok",
ok));
381 archive(cereal::make_nvp(
"error",
error));
388 template<
class U = T>
392 template<
class F = E>
397 template<
class U = T>
404 template<
class F = E>
411 template<
class U = T>
413 return isOk() && *this->
ok() == *
ok;
417 template<
class U = T>
419 return !(*
this ==
ok);
423 template<
class F = E>
429 template<
class F = E>
431 return !(*
this ==
error);
435 template<
class U,
class F>
437 return ((
isOk() && other.
isOk() && *
ok() == *other.
ok()) ||
442 template<
class U,
class F>
444 return !(*
this == other);
451 return result_.which() == 0;
453 explicit operator bool()
const {
468 return *boost::get<OkType>(result_);
481 return *boost::get<ErrorType>(result_);
488 const T&
expect(
const std::string &mesg)
const {
490 return *boost::get<OkType>(result_);
492 throw std::runtime_error(mesg);
502 return expect(
"result is not okay");
526 typename std::enable_if<is_invocable<Fn, ErrorValue>::value,
const Result>::type
541 return boost::get<OkType>(result_);
557 template<
class Exception = E>
562 throw Exception(*
error());
567 template<
class Exception = E>
581 typename std::enable_if<is_invocable<Fn, OkValue>::value,
const Result>::type
598 return boost::get<ErrorType>(result_);
607 throw std::runtime_error(mesg);
609 return *boost::get<ErrorType>(result_);
638 Optional<Result<typename T::Value, E>>
652 Result<typename OkValue::OkValue, E> flatten()
const {
691 template <
typename F>
Error(const Error &other)
Copy constructor.
Error & operator=(const Value &error)
Assignment.
const Value & operator*() const
Dereference to obtain error.
Error & operator=(const Error &other)
Assignment.
const Value * operator->() const
Dereference to obtain pointer to error.
Error(const Value &error)
Construct from a value.
const Value & operator*() const
Dereference to obtain error.
const Value * operator->() const
Dereference to obtain pointer to error.
Error(const E &error)
Construct from a value.
Error & operator=(const Value &error)
Assignment.
Error(const Error &other)
Copy constructor.
Error & operator=(const Error &other)
Assignment.
Ok & operator=(const Ok &other)
Assignment.
const Value * operator->() const
Dereference to obtain pointer.
Ok & operator=(const Value &ok)
Assignment.
Ok(const Ok &other)
Copy constructor.
const Value & operator*() const
Dereference to obtain value.
Ok(const Value &ok)
Construct from an value.
Holds a value or nothing.
Result containing a value or an error.
const T orElse(const T &dflt) const
Returns the contained Ok value or a provided default.
bool operator==(const Result< U, F > &other) const
Test whether this result is equal to the other result.
bool operator!=(const Ok< U > &ok) const
Test whether this result does not have the specified Ok value.
const T & expect(const std::string &mesg) const
Returns the success value or throws an exception.
const Sawyer::Optional< T > ok() const
Convert to Optional<T>.
bool contains(const U &value) const
Returns true if this result contains the specified okay value.
std::enable_if< is_invocable< Fn, ErrorValue >::value, constResult >::type orElse(Fn fn) const
Returns the contained Ok value, or calls a function.
const E & expectError(const std::string &mesg) const
Returns the error value or throws an exception.
bool operator==(const Ok< U > &ok) const
Test whether this result has the specified Ok value.
Result & operator=(const Error< F > &error)
Assign an Error value to this result.
const E & unwrapError() const
Returns the error value or throws an exception.
const T & orDefault() const
Returns the okay value or a default constructed value.
const T & operator*() const
Returns the success value or throws an exception.
const Result< U, E > andThen(const Result< U, E > &other) const
Returns this error or the other result.
const T & unwrap() const
Returns the success value or throws an exception.
const Result & assignTo(U &out) const
Conditionally save a value.
bool operator==(const Error< F > &error) const
Test whether this result has the specified Error value.
const Sawyer::Optional< E > error() const
Convert to Optional<E>.
const Result< T, F > orElse(const Result< T, F > &other) const
Returns this value or the other result.
bool isError() const
Returns true if the result is an error.
bool operator!=(const Result< U, F > &other) const
Test whether this result is unequal to the other result.
Result & assignTo(U &out) const
Conditionally save a value.
const T * operator->() const
Returns a pointer to the success value, or thows an exception.
bool operator!=(const Error< F > &error) const
Test whether this result does not have the specified Error value.
const T & orThrow(const Exception &e) const
Returns the value or throws an exception constructed from the specified value.
Result & operator=(const Ok< U > &ok)
Assign an Ok value to this result.
bool containsError(const F &error) const
Returns true if this result contains the specified error value.
std::enable_if< is_invocable< Fn, OkValue >::value, constResult >::type andThen(Fn fn) const
Returns the contained Error value, or calls a function.
auto fmap(F &&f) -> Result< decltype(f(unwrap())), E >
Conditionally apply a functor f to the contents of a Result.
const T & orThrow() const
Returns the value or throws an exception.
bool isOk() const
Returns true if the result is okay.
Error< T > makeError(const T &value)
Conventient way to constructo an Error value before C++17.
Ok< T > makeOk(const T &value)
Conventient way to constructo an Ok value before C++17.