Code

rework maybe so storage is customizable and can be optimized on a
[inkscape.git] / src / libnr / nr-maybe.h
1 #ifndef __NR_MAYBE_H__
2 #define __NR_MAYBE_H__
4 /*
5  * Nullable values for C++
6  *
7  * Copyright 2004, 2007  MenTaLguY <mental@rydia.net>
8  *
9  * This code is licensed under the GNU GPL; see COPYING for more information.
10  */
12 #if HAVE_CONFIG_H
13 #include "config.h"
14 #endif
16 #include <stdexcept>
17 #include <string>
19 namespace NR {
21 class IsNothing : public std::domain_error {
22 public:
23     IsNothing() : domain_error(std::string("Is nothing")) {}
24 };
26 struct Nothing {};
28 template <typename T>
29 class MaybeStorage {
30 public:
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; }
39 private:
40     T _value;
41     bool _is_nothing;
42 };
44 template <typename T>
45 class MaybeStorage<T &> {
46 public:
47     MaybeStorage() : _ref(NULL) {}
48     MaybeStorage(T &value) : _ref(&value) {}
50     bool is_nothing() const { return !_ref; }
51     T &value() const { return *_ref; }
53 private:
54     T *_ref;
55 };
57 template <typename T>
58 class Maybe {
59 public:
60     Maybe() {}
62     Maybe(Nothing) {}
64     Maybe(T &t) : _storage(t) {}
65     Maybe(T const &t) : _storage(t) {}
67     Maybe(Maybe &m) : _storage(m._storage) {}
68     Maybe(Maybe const &m) : _storage(m._storage) {}
70     template <typename T2>
71     Maybe(Maybe<T2> &m) {
72         if (m) {
73             _storage = *m;
74         }
75     }
76     template <typename T2>
77     Maybe(Maybe<T2> const &m) {
78         if (m) {
79             _storage = *m;
80         }
81     }
83     template <typename T2>
84     Maybe(Maybe<T2 &> m) {
85         if (m) {
86             _storage = *m;
87         }
88     }
89     template <typename T2>
90     Maybe(Maybe<T2 const &> m) {
91         if (m) {
92             _storage = *m;
93         }
94     }
96     operator bool() const { return !_storage.is_nothing(); }
98     T const &operator*() const throw(IsNothing) {
99         if (_storage.is_nothing()) {
100             throw IsNothing();
101         } else {
102             return _storage.value();
103         }
104     }
105     T &operator*() throw(IsNothing) {
106         if (_storage.is_nothing()) {
107             throw IsNothing();
108         } else {
109             return _storage.value();
110         }
111     }
113     T const *operator->() const throw(IsNothing) {
114         if (_storage.is_nothing()) {
115             throw IsNothing();
116         } else {
117             return &_storage.value();
118         }
119     }
120     T *operator->() throw(IsNothing) {
121         if (_storage.is_nothing()) {
122             throw IsNothing();
123         } else {
124             return &_storage.value();
125         }
126     }
128     template <typename T2>
129     bool operator==(NR::Maybe<T2> const &other) const {
130         bool is_nothing = _storage.is_nothing();
131         if ( is_nothing || !other ) {
132             return is_nothing && !other;
133         } else {
134             return _storage.value() == *other;
135         }
136     }
137     template <typename T2>
138     bool operator!=(NR::Maybe<T2> const &other) const {
139         bool is_nothing = _storage.is_nothing();
140         if ( is_nothing || !other ) {
141             return !is_nothing || other;
142         } else {
143             return _storage.value() != *other;
144         }
145     }
147 private:
148     MaybeStorage<T> _storage;
149 };
151 } /* namespace NR */
153 #endif
155 /*
156   Local Variables:
157   mode:c++
158   c-file-style:"stroustrup"
159   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
160   indent-tabs-mode:nil
161   fill-column:99
162   End:
163 */
164 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :