Code

write no/unset fill/stroke to current style
[inkscape.git] / src / libnr / nr-maybe.h
1 #ifndef __NR_MAYBE_H__
2 #define __NR_MAYBE_H__
4 /*
5  * Functionalesque "Maybe" class
6  *
7  * Copyright 2004  MenTaLguY
8  *
9  * Authors:
10  *   MenTaLguY <mental@rydia.net>
11  *
12  * This code is licensed under the GNU GPL; see COPYING for more information.
13  */
15 #if HAVE_CONFIG_H
16 #include "config.h"
17 #endif
19 #include <stdexcept>
20 #include <typeinfo>
21 #include <string>
23 namespace NR {
25 /** An exception class for run-time type errors */
26 template <typename T>
27 class IsNot : public std::domain_error {
28 public:
29     IsNot() : domain_error(std::string("Is not ") + typeid(T).name()) {}
30 };
32 /** A type with only one value, which (in principle) is only equal to itself.
33  *
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.
37  *
38  *  Such types should also provide a casting operator to Nothing, obviously.
39  */
40 struct Nothing {
41     bool operator==(Nothing n) { return true; }
42     bool operator!=(Nothing n) { return false; }
43     template <typename T>
44     bool operator==(T t) { return t == *this; }
45     template <typename T>
46     bool operator!=(T t) { return t != *this; }
47 };
49 template <typename T>
50 bool operator==(T t, Nothing n) { return false; }
51 template <typename T>
52 bool operator!=(T t, Nothing n) { return !( t == n ); }
54 template <typename T>
55 struct MaybeTraits;
57 template <typename T>
58 class Maybe {
59 public:
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>) {
77         if (_is_nothing) {
78             throw IsNot<T>();
79         } else {
80             return traits::from_storage(_t);
81         }
82     }
84     operator reference() const throw(IsNot<T>) {
85         if (_is_nothing) {
86             throw IsNot<T>();
87         } else {
88             return traits::from_storage(_t);
89         }
90     }
91     operator Nothing() const throw(IsNot<Nothing>) {
92         if (!_is_nothing) {
93             throw IsNot<Nothing>();
94         } else {
95             return Nothing();
96         }
97     }
99     bool operator==(Nothing n) { return _is_nothing; }
100     bool operator==(reference r) {
101         return traits::from_storage(_t) == r;
102     }
104 private:
105     bool _is_nothing;
106     storage _t;
107 };
109 /* traits classes used by Maybe */
111 template <typename T>
112 struct MaybeTraits {
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; }
117 };
119 template <typename T>
120 struct MaybeTraits<T&> {
121     typedef T *storage;
122     typedef T &reference;
123     static storage to_storage(reference t) { return &t; }
124     static reference from_storage(storage t) { return *t; }
125 };
127 } /* namespace NR */
129 #endif
131 /*
132   Local Variables:
133   mode:c++
134   c-file-style:"stroustrup"
135   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
136   indent-tabs-mode:nil
137   fill-column:99
138   End:
139 */
140 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :