8#ifndef Sawyer_Optional_H
9#define Sawyer_Optional_H
11#include <Sawyer/Sawyer.h>
12#include <boost/type_traits/aligned_storage.hpp>
13#include <boost/type_traits/type_with_alignment.hpp>
39 template<
class T>
explicit Nothing(T) {}
40 template<
class T>
Nothing& operator=(T) {
return *
this; }
41 bool operator==(
const Nothing&)
const {
return true; }
42 bool operator!=(
const Nothing&)
const {
return false; }
43 bool operator>(
const Nothing&)
const {
return false; }
44 bool operator>=(
const Nothing&)
const {
return true; }
45 bool operator<(
const Nothing&)
const {
return false; }
46 bool operator<=(
const Nothing&)
const {
return true; }
59 union SAWYER_MAY_ALIAS MayAlias {
60 unsigned char data_[
sizeof(T)];
61 BOOST_DEDUCED_TYPENAME boost::type_with_alignment<boost::alignment_of<T>::value >::type aligner_;
66 void *address() {
return &mayAlias_; }
67 const void*address()
const {
return &mayAlias_; }
69#ifdef SAWYER_HAVE_BOOST_SERIALIZATION
71 friend class boost::serialization::access;
74 void save(S &s,
const unsigned )
const {
75 s <<BOOST_SERIALIZATION_NVP(isEmpty_);
77 s <<boost::serialization::make_nvp(
"value",
get());
81 void load(S &s,
const unsigned ) {
84 s >>boost::serialization::make_nvp(
"isEmpty_", skip);
87 s >>boost::serialization::make_nvp(
"value",
get());
91 BOOST_SERIALIZATION_SPLIT_MEMBER();
94#ifdef SAWYER_HAVE_CEREAL
96 friend class cereal::access;
98 template<
class Archive>
99 void CEREAL_SAVE_FUNCTION_NAME(Archive &archive)
const {
100 archive(cereal::make_nvp(
"isEmpty", isEmpty_));
102 archive(cereal::make_nvp(
"value",
get()));
105 template<
class Archive>
106 void CEREAL_LOAD_FUNCTION_NAME(Archive &archive) {
108 bool isEmpty =
false;
109 archive(CEREAL_NVP(isEmpty));
112 archive(cereal::make_nvp(
"value",
get()));
130 new (address())
Value(v);
143 isEmpty_ = other.isEmpty_;
145 const Value &otherValue = *other;
146 new (address())
Value(otherValue);
155 Value &thisValue = **
this;
166 new (address())
Value(value);
168 Value &thisValue = **
this;
181 Value &thisValue = **
this;
195 if (isEmpty_ && !other.isEmpty_) {
196 const Value &otherValue = *other;
197 new (address())
Value(otherValue);
198 }
else if (!isEmpty_) {
199 if (other.isEmpty_) {
200 Value &thisValue = **
this;
203 Value &thisValue = **
this;
204 const Value &otherValue = *other;
205 thisValue = otherValue;
208 isEmpty_ = other.isEmpty_;
231 throw std::domain_error(
"dereferenced nothing");
232 return *
reinterpret_cast<const Value*
>(address());
236 throw std::domain_error(
"dereferenced nothing");
237 return *
reinterpret_cast<Value*
>(address());
268 return isEmpty_ ? dflt : **
this;
271 return isEmpty_ ? dflt : **
this;
274 return isEmpty_ ? other : *
this;
284 return isEmpty_ ? *this :
Optional(value);
287 return isEmpty_ ? *this :
Optional(value);
290 return isEmpty_ ? *this : other;
306 return isEmpty_ ?
Value() : **
this;
348 return (isEmpty_ && other.isEmpty_) || (!isEmpty_ && !other.isEmpty_ &&
get()==other.
get());
351 return !isEmpty_ &&
get()==other;
363 template <
typename F>
375 typedef void(
Optional::*unspecified_bool)() const;
376 void this_type_does_not_support_comparisons()
const {}
389 operator unspecified_bool()
const {
390 return isEmpty_ ? 0 : &Optional::this_type_does_not_support_comparisons;
402template<
typename T,
typename U>
403bool operator==(
const Optional<T> &lhs,
const U&) {
404 lhs.this_type_does_not_support_comparisons();
408template<
typename T,
typename U>
409bool operator!=(
const Optional<T> &lhs,
const U&) {
410 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.