19
16
#include <stdexcept>
25
/** An exception class for run-time type errors */
27
class IsNot : public std::domain_error {
29
IsNot() : domain_error(std::string("Is not ") + typeid(T).name()) {}
32
/** A type with only one value, which (in principle) is only equal to itself.
34
* Types that may (at runtime) pretend to be Nothing need only provide an
35
* operator bool operator==(Type, Nothing); the rest of the operator
36
* definitions will be taken care of automatically.
38
* Such types should also provide a casting operator to Nothing, obviously.
41
bool operator==(Nothing n) { return true; }
42
bool operator!=(Nothing n) { return false; }
44
bool operator==(T t) { return t == *this; }
46
bool operator!=(T t) { return t != *this; }
50
bool operator==(T t, Nothing n) { return false; }
52
bool operator!=(T t, Nothing n) { return !( t == n ); }
21
class IsNothing : public std::domain_error {
23
IsNothing() : domain_error(std::string("Is nothing")) {}
31
MaybeStorage() : _is_nothing(true) {}
32
MaybeStorage(T const &value)
33
: _value(value), _is_nothing(false) {}
35
bool is_nothing() const { return _is_nothing; }
36
T &value() { return _value; }
37
T const &value() const { return _value; }
57
44
template <typename T>
60
typedef MaybeTraits<T> traits;
61
typedef typename traits::storage storage;
62
typedef typename traits::reference reference;
64
Maybe(Nothing n) : _is_nothing(true), _t() {}
66
Maybe(const Maybe<T> &m) : _is_nothing(m._is_nothing), _t(m._t) {}
68
template <typename T2>
69
Maybe(const Maybe<T2> &m)
70
: _is_nothing(m._is_nothing),
71
_t(traits::to_storage(MaybeTraits<T2>::from_storage(m._t))) {}
73
template <typename T2>
74
Maybe(T2 t) : _is_nothing(false), _t(traits::to_storage(t)) {}
76
reference assume() const throw(IsNot<T>) {
80
return traits::from_storage(_t);
84
operator reference() const throw(IsNot<T>) {
88
return traits::from_storage(_t);
91
operator Nothing() const throw(IsNot<Nothing>) {
93
throw IsNot<Nothing>();
99
bool operator==(Nothing n) { return _is_nothing; }
100
bool operator==(reference r) {
101
return traits::from_storage(_t) == r;
109
/* traits classes used by Maybe */
111
template <typename T>
113
typedef T const storage;
114
typedef T const &reference;
115
static reference to_storage(reference t) { return t; }
116
static reference from_storage(reference t) { return t; }
119
template <typename T>
120
struct MaybeTraits<T&> {
122
typedef T &reference;
123
static storage to_storage(reference t) { return &t; }
124
static reference from_storage(storage t) { return *t; }
49
Maybe(T const &t) : _storage(t) {}
50
Maybe(Maybe const &m) : _storage(m._storage) {}
52
template <typename T2>
53
Maybe(Maybe<T2> const &m) {
59
template <typename T2>
60
Maybe(Maybe<T2 const &> m) {
66
operator bool() const { return !_storage.is_nothing(); }
68
T const &operator*() const throw(IsNothing) {
69
if (_storage.is_nothing()) {
72
return _storage.value();
75
T &operator*() throw(IsNothing) {
76
if (_storage.is_nothing()) {
79
return _storage.value();
83
T const *operator->() const throw(IsNothing) {
84
if (_storage.is_nothing()) {
87
return &_storage.value();
90
T *operator->() throw(IsNothing) {
91
if (_storage.is_nothing()) {
94
return &_storage.value();
98
template <typename T2>
99
bool operator==(Maybe<T2> const &other) const {
100
bool is_nothing = _storage.is_nothing();
101
if ( is_nothing || !other ) {
102
return is_nothing && !other;
104
return _storage.value() == *other;
107
template <typename T2>
108
bool operator!=(Maybe<T2> const &other) const {
109
bool is_nothing = _storage.is_nothing();
110
if ( is_nothing || !other ) {
111
return !is_nothing || other;
113
return _storage.value() != *other;
118
MaybeStorage<T> _storage;
121
template <typename T>
124
Maybe() : _ref(NULL) {}
125
Maybe(Nothing) : _ref(NULL) {}
126
Maybe(T &t) : _ref(&t) {}
128
template <typename T2>
129
Maybe(Maybe<T2> const &m) {
135
template <typename T2>
136
Maybe(Maybe<T2 &> m) {
142
template <typename T2>
143
Maybe(Maybe<T2 const &> m) {
149
operator bool() const { return _ref; }
151
T &operator*() const throw(IsNothing) {
158
T *operator->() const throw(IsNothing) {
166
template <typename T2>
167
bool operator==(Maybe<T2> const &other) const {
168
if ( !_ref || !other ) {
169
return !_ref && !other;
171
return *_ref == *other;
174
template <typename T2>
175
bool operator!=(Maybe <T2> const &other) const {
176
if ( !_ref || !other ) {
177
return _ref || other;
179
return *_ref != *other;
127
187
} /* namespace NR */