Code

fix by dvlierop2 for snapping bugs 1579556 and 1579587
[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 Maybe {
30 public:
31     Maybe(Nothing) : _is_nothing(true) {}
32     Maybe(T const &t) : _t(t), _is_nothing(false) {}
33     Maybe(Maybe const &m) : _t(m._t), _is_nothing(m._is_nothing) {}
35     template <typename T2> Maybe(Maybe<T2> const &m)
36     : _is_nothing(!m)
37     {
38         if (m) {
39             _t = *m;
40         }
41     }
43     template <typename T2> Maybe(T2 const &t)
44     : _t(t), _is_nothing(false) {}
46     operator bool() const { return !_is_nothing; }
48     T const &operator*() const throw(IsNothing) {
49         if (_is_nothing) {
50             throw IsNothing();
51         } else {
52             return _t;
53         }
54     }
55     T &operator*() throw(IsNothing) {
56         if (_is_nothing) {
57             throw IsNothing();
58         } else {
59             return _t;
60         }
61     }
63     T const *operator->() const throw(IsNothing) {
64         if (_is_nothing) {
65             throw IsNothing();
66         } else {
67             return &_t;
68         }
69     }
70     T *operator->() throw(IsNothing) {
71         if (_is_nothing) {
72             throw IsNothing();
73         } else {
74             return &_t;
75         }
76     }
78     template <typename T2>
79     bool operator==(NR::Maybe<T2> const &other) const {
80         if ( _is_nothing || !other ) {
81             return _is_nothing && !other;
82         } else {
83             return _t == *other;
84         }
85     }
86     template <typename T2>
87     bool operator!=(NR::Maybe<T2> const &other) const {
88         if ( _is_nothing || !other ) {
89             return !_is_nothing || other;
90         } else {
91             return _t != *other;
92         }
93     }
95 private:
96     T _t;
97     bool _is_nothing;
98 };
100 template <typename T>
101 class Maybe<T const> {
102 public:
103     Maybe(Nothing) : _is_nothing(true) {}
104     Maybe(T const &t) : _t(t), _is_nothing(false) {}
105     Maybe(Maybe const &m) : _t(m._t), _is_nothing(m._is_nothing) {}
107     template <typename T2> Maybe(Maybe<T2> const &m)
108     : _is_nothing(!m)
109     {
110         if (m) {
111             _t = *m;
112         }
113     }
115     template <typename T2> Maybe(T2 const &t)
116     : _t(t), _is_nothing(false) {}
118     operator bool() const { return !_is_nothing; }
120     T const &operator*() const throw(IsNothing) {
121         if (_is_nothing) {
122             throw IsNothing();
123         } else {
124             return _t;
125         }
126     }
128     T const *operator->() const throw(IsNothing) {
129         if (_is_nothing) {
130             throw IsNothing();
131         } else {
132             return &_t;
133         }
134     }
136     template <typename T2>
137     bool operator==(NR::Maybe<T2> const &other) const {
138         if ( _is_nothing || !other ) {
139             return _is_nothing && !other;
140         } else {
141             return _t == *other;
142         }
143     }
144     template <typename T2>
145     bool operator!=(NR::Maybe<T2> const &other) const {
146         if ( _is_nothing || !other ) {
147             return !_is_nothing || other;
148         } else {
149             return _t != *other;
150         }
151     }
153 private:
154     T const _t;
155     bool _is_nothing;
156 };
158 template <typename T>
159 class Maybe<T &> {
160 public:
161     Maybe(Nothing) : _ref(NULL) {}
162     Maybe(T &t) : _ref(&t) {}
163     Maybe(Maybe const &m) : _ref(m._ref) {}
165     template <typename T2> Maybe(Maybe<T2> const &m)
166     : _ref( m ? &*m : NULL ) {}
167     template <typename T2> Maybe(T2 &t) : _ref(&t) {}
169     operator bool() const { return _ref; }
171     T &operator*() const throw(IsNothing) {
172         if (_ref) {
173             throw IsNothing();
174         } else {
175             return *_ref;
176         }
177     }
179     T *operator->() const throw(IsNothing) {
180         if (_ref) {
181             throw IsNothing();
182         } else {
183             return _ref;
184         }
185     }
187     template <typename T2>
188     bool operator==(NR::Maybe<T2> const &other) const {
189         if ( !_ref || !other ) {
190             return !_ref && !other;
191         } else {
192             return *_ref == *other;
193         }
194     }
195     template <typename T2>
196     bool operator!=(NR::Maybe<T2> const &other) const {
197         if ( !_ref || !other ) {
198             return _ref || other;
199         } else {
200             return *_ref != *other;
201         }
202     }
204 private:
205     void operator=(Maybe const &); // no assign
207     T *_ref;
208 };
210 } /* namespace NR */
212 #endif
214 /*
215   Local Variables:
216   mode:c++
217   c-file-style:"stroustrup"
218   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
219   indent-tabs-mode:nil
220   fill-column:99
221   End:
222 */
223 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :