Code

Super duper mega (fun!) commit: replaced encoding=utf-8 with fileencoding=utf-8 in...
[inkscape.git] / src / libnr / nr-maybe.h
index e834df51d9881415175d8cd3df17d9acc4315a0a..1413f69d2ce8ec533bc4e3de280a09fe5d477fdd 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <stdexcept>
 #include <string>
+#include <algorithm>
 
 namespace NR {
 
@@ -25,197 +26,163 @@ public:
 
 struct Nothing {};
 
+template <typename T>
+class MaybeStorage {
+public:
+    MaybeStorage() : _is_nothing(true) {}
+    MaybeStorage(T const &value)
+    : _value(value), _is_nothing(false) {}
+
+    bool is_nothing() const { return _is_nothing; }
+    T &value() { return _value; }
+    T const &value() const { return _value; }
+
+private:
+    T _value;
+    bool _is_nothing;
+};
+
 template <typename T>
 class Maybe {
 public:
-    Maybe(Nothing) : _t(), _is_nothing(true) {}
-    Maybe(T const &t) : _t(t), _is_nothing(false) {}
-    Maybe(Maybe const &m) : _t(m._t), _is_nothing(m._is_nothing) {}
+    Maybe() {}
+    Maybe(Nothing) {}
+    Maybe(T const &t) : _storage(t) {}
+    Maybe(Maybe const &m) : _storage(m._storage) {}
 
-    template <typename T2> Maybe(Maybe<T2> const &m)
-    : _t(m._t), _is_nothing(m._is_nothing) {}
+    template <typename T2>
+    Maybe(Maybe<T2> const &m) {
+        if (m) {
+            _storage = *m;
+        }
+    }
 
-    template <typename T2> Maybe(T2 const &t)
-    : _t(t), _is_nothing(false) {}
+    template <typename T2>
+    Maybe(Maybe<T2 const &> m) {
+        if (m) {
+            _storage = *m;
+        }
+    }
 
-    operator bool() const { return !_is_nothing; }
+    operator bool() const { return !_storage.is_nothing(); }
 
     T const &operator*() const throw(IsNothing) {
-        if (_is_nothing) {
+        if (_storage.is_nothing()) {
             throw IsNothing();
         } else {
-            return _t;
+            return _storage.value();
         }
     }
     T &operator*() throw(IsNothing) {
-        if (_is_nothing) {
+        if (_storage.is_nothing()) {
             throw IsNothing();
         } else {
-            return _t;
+            return _storage.value();
         }
     }
 
     T const *operator->() const throw(IsNothing) {
-        if (_is_nothing) {
+        if (_storage.is_nothing()) {
             throw IsNothing();
         } else {
-            return &_t;
+            return &_storage.value();
         }
     }
     T *operator->() throw(IsNothing) {
-        if (_is_nothing) {
+        if (_storage.is_nothing()) {
             throw IsNothing();
         } else {
-            return &_t;
+            return &_storage.value();
         }
     }
 
     template <typename T2>
-    bool operator==(NR::Maybe<T2> const &other) const {
-        if ( _is_nothing || other._is_nothing ) {
-            return _is_nothing == other._is_nothing;
+    bool operator==(Maybe<T2> const &other) const {
+        bool is_nothing = _storage.is_nothing();
+        if ( is_nothing || !other ) {
+            return is_nothing && !other;
         } else {
-            return _t == other._t;
+            return _storage.value() == *other;
         }
     }
     template <typename T2>
-    bool operator!=(NR::Maybe<T2> const &other) const {
-        if ( _is_nothing || other._is_nothing ) {
-            return _is_nothing != other._is_nothing;
+    bool operator!=(Maybe<T2> const &other) const {
+        bool is_nothing = _storage.is_nothing();
+        if ( is_nothing || !other ) {
+            return !is_nothing || other;
         } else {
-            return _t != other._t;
+            return _storage.value() != *other;
         }
     }
 
 private:
-    T _t;
-    bool _is_nothing;
+    MaybeStorage<T> _storage;
 };
 
 template <typename T>
-class Maybe<T const> {
+class Maybe<T &> {
 public:
-    Maybe(Nothing) : _t(), _is_nothing(true) {}
-    Maybe(T const &t) : _t(t), _is_nothing(false) {}
-    Maybe(Maybe const &m) : _t(m._t), _is_nothing(m._is_nothing) {}
-
-    template <typename T2> Maybe(Maybe<T2> const &m)
-    : _t(m._t), _is_nothing(m._is_nothing) {}
-
-    template <typename T2> Maybe(T2 const &t)
-    : _t(t), _is_nothing(false) {}
-
-    operator bool() const { return !_is_nothing; }
-
-    T const &operator*() const throw(IsNothing) {
-        if (_is_nothing) {
-            throw IsNothing();
-        } else {
-            return _t;
-        }
-    }
+    Maybe() : _ref(NULL) {}
+    Maybe(Nothing) : _ref(NULL) {}
+    Maybe(T &t) : _ref(&t) {}
 
-    T const *operator->() const throw(IsNothing) {
-        if (_is_nothing) {
-            throw IsNothing();
-        } else {
-            return &_t;
-        }
+    template <typename T2>
+    Maybe(Maybe<T2> const &m) {
+        if (m) {
+            _ref = &*m;
+        } 
     }
 
     template <typename T2>
-    bool operator==(NR::Maybe<T2> const &other) const {
-        if ( _is_nothing || other._is_nothing ) {
-            return _is_nothing == other._is_nothing;
-        } else {
-            return _t == other._t;
+    Maybe(Maybe<T2 &> m) {
+        if (m) {
+            _ref = *m;
         }
     }
+
     template <typename T2>
-    bool operator!=(NR::Maybe<T2> const &other) const {
-        if ( _is_nothing || other._is_nothing ) {
-            return _is_nothing != other._is_nothing;
-        } else {
-            return _t != other._t;
+    Maybe(Maybe<T2 const &> m) {
+        if (m) {
+            _ref = *m;
         }
     }
 
-private:
-    T const _t;
-    bool _is_nothing;
-};
-
-template <typename T>
-class Maybe<T &> {
-public:
-    Maybe(Nothing) : _t(), _is_nothing(true) {}
-    Maybe(T &t) : _t(&t), _is_nothing(false) {}
-    Maybe(Maybe const &m) : _t(m._t), _is_nothing(m._is_nothing) {}
-
-    template <typename T2> Maybe(Maybe<T2> const &m)
-    : _t(&m._t), _is_nothing(m._is_nothing) {}
-
-    template <typename T2> Maybe(Maybe<T2 &> const &m)
-    : _t(m._t), _is_nothing(m._is_nothing) {}
-
-    template <typename T2> Maybe(T2 &t)
-    : _t(&t), _is_nothing(false) {};
-
-    operator bool() const { return !_is_nothing; }
+    operator bool() const { return _ref; }
 
     T &operator*() const throw(IsNothing) {
-        if (_is_nothing) {
+        if (!_ref) {
             throw IsNothing();
         } else {
-            return *_t;
+            return *_ref;
         }
     }
-
     T *operator->() const throw(IsNothing) {
-        if (_is_nothing) {
+        if (!_ref) {
             throw IsNothing();
         } else {
-            return _t;
+            return _ref;
         }
     }
 
     template <typename T2>
-    bool operator==(NR::Maybe<T2> const &other) const {
-        if ( _is_nothing || other._is_nothing ) {
-            return _is_nothing == other._is_nothing;
+    bool operator==(Maybe<T2> const &other) const {
+        if ( !_ref || !other ) {
+            return !_ref && !other;
         } else {
-            return *_t == other._t;
+            return *_ref == *other;
         }
     }
     template <typename T2>
-    bool operator!=(NR::Maybe<T2> const &other) const {
-        if ( _is_nothing || other._is_nothing ) {
-            return _is_nothing != other._is_nothing;
+    bool operator!=(Maybe <T2> const &other) const {
+        if ( !_ref || !other ) {
+            return _ref || other;
         } else {
-            return *_t != other._t;
-        }
-    }
-
-    template <typename T2>
-    bool operator==(NR::Maybe<T2 &> const &other) const {
-        if ( _is_nothing || other._is_nothing ) {
-            return _is_nothing == other._is_nothing;
-        } else {
-            return *_t == *other._t;
-        }
-    }
-    template <typename T2>
-    bool operator!=(NR::Maybe<T2 &> const &other) const {
-        if ( _is_nothing || other._is_nothing ) {
-            return _is_nothing != other._is_nothing;
-        } else {
-            return *_t != *other._t;
+            return *_ref != *other;
         }
     }
 
 private:
-    T *_t;
-    bool _is_nothing;
+    T *_ref;
 };
 
 } /* namespace NR */
@@ -231,4 +198,4 @@ private:
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :