8#ifndef Sawyer_Optional_H
9#define Sawyer_Optional_H
11#include <Sawyer/Sawyer.h>
37 template<
class T>
explicit Nothing(T) {}
38 template<
class T>
Nothing& operator=(T) {
return *
this; }
39 bool operator==(
const Nothing&)
const {
return true; }
40 bool operator!=(
const Nothing&)
const {
return false; }
41 bool operator>(
const Nothing&)
const {
return false; }
42 bool operator>=(
const Nothing&)
const {
return true; }
43 bool operator<(
const Nothing&)
const {
return false; }
44 bool operator<=(
const Nothing&)
const {
return true; }
55 alignas(
alignof(T))
unsigned char data_[
sizeof(T)];
58 void *address() {
return data_; }
59 const void*address()
const {
return &data_; }
61#ifdef SAWYER_HAVE_BOOST_SERIALIZATION
63 friend class boost::serialization::access;
66 void save(S &s,
const unsigned )
const {
67 s <<BOOST_SERIALIZATION_NVP(isEmpty_);
69 s <<boost::serialization::make_nvp(
"value",
get());
73 void load(S &s,
const unsigned ) {
76 s >>boost::serialization::make_nvp(
"isEmpty_", skip);
79 s >>boost::serialization::make_nvp(
"value",
get());
83 BOOST_SERIALIZATION_SPLIT_MEMBER();
86#ifdef SAWYER_HAVE_CEREAL
88 friend class cereal::access;
90 template<
class Archive>
91 void CEREAL_SAVE_FUNCTION_NAME(Archive &archive)
const {
92 archive(cereal::make_nvp(
"isEmpty", isEmpty_));
94 archive(cereal::make_nvp(
"value",
get()));
97 template<
class Archive>
98 void CEREAL_LOAD_FUNCTION_NAME(Archive &archive) {
100 bool isEmpty =
false;
101 archive(CEREAL_NVP(isEmpty));
104 archive(cereal::make_nvp(
"value",
get()));
122 new (address())
Value(v);
135 isEmpty_ = other.isEmpty_;
137 const Value &otherValue = *other;
138 new (address())
Value(otherValue);
147 Value &thisValue = **
this;
158 new (address())
Value(value);
160 Value &thisValue = **
this;
173 Value &thisValue = **
this;
187 if (isEmpty_ && !other.isEmpty_) {
188 const Value &otherValue = *other;
189 new (address())
Value(otherValue);
190 }
else if (!isEmpty_) {
191 if (other.isEmpty_) {
192 Value &thisValue = **
this;
195 Value &thisValue = **
this;
196 const Value &otherValue = *other;
197 thisValue = otherValue;
200 isEmpty_ = other.isEmpty_;
223 throw std::domain_error(
"dereferenced nothing");
224 return *
reinterpret_cast<const Value*
>(address());
228 throw std::domain_error(
"dereferenced nothing");
229 return *
reinterpret_cast<Value*
>(address());
260 return isEmpty_ ? dflt : **
this;
263 return isEmpty_ ? dflt : **
this;
266 return isEmpty_ ? other : *
this;
276 return isEmpty_ ? *this :
Optional(value);
279 return isEmpty_ ? *this :
Optional(value);
282 return isEmpty_ ? *this : other;
298 return isEmpty_ ?
Value() : **
this;
340 return (isEmpty_ && other.isEmpty_) || (!isEmpty_ && !other.isEmpty_ &&
get()==other.
get());
343 return !isEmpty_ &&
get()==other;
355 template <
typename F>
367 typedef void(
Optional::*unspecified_bool)() const;
368 void this_type_does_not_support_comparisons()
const {}
381 operator unspecified_bool()
const {
382 return isEmpty_ ? 0 : &Optional::this_type_does_not_support_comparisons;
381 operator unspecified_bool()
const {
…}
394template<
typename T,
typename U>
395bool operator==(
const Optional<T> &lhs,
const U&) {
396 lhs.this_type_does_not_support_comparisons();
400template<
typename T,
typename U>
401bool operator!=(
const Optional<T> &lhs,
const U&) {
402 lhs.this_type_does_not_support_comparisons();
Holds a value or nothing.
Optional & operator=(const Nothing &)
Nothing assignment.
const Value & orElse(Value &dflt)
Obtain value or something else.
const Value & operator*() const
Dereference to obtain value.
auto fmap(F &&f) -> Optional< decltype(f(get()))>
Conditionally apply a functor f to the contents of an Optional.
T Value
Type of stored value.
const Optional & andThen(const Optional &other) const
If a value is present, return something else.
const Value * operator->() const
Obtain a pointer to the value.
Value orDefault() const
Obtain a value or a default.
Optional(const Value &v)
Construct from value.
Optional & operator=(const Value &value)
Value assignment.
const Optional orElse(const Optional &other) const
Obtain value or something else.
Optional & operator=(const Optional &other)
Optional assignment.
Optional(const Nothing &)
Construct from nothing.
Value * operator->()
Obtain a pointer to the value.
Optional andTHen(Value &value) const
If a value is present, return something else.
bool isEqual(const Nothing &) const
Compare two values.
Value & operator*()
Dereference to obtain value.
void reset()
Reset as if default-constructed.
const Value & orElse(const Value &dflt) const
Obtain value or something else.
const Value & get() const
Dereference to obtain value.
Optional()
Default constructs nothing.
Value & get()
Dereference to obtain value.
bool assignTo(U &out) const
Conditionally save a value.
bool isEqual(const Optional &other) const
Compare two values.
Optional(const Optional &other)
Copy constructor.
Optional andThen(const Value &value) const
If a value is present, return something else.
bool isEqual(const Value &other) const
Compare two values.