1 | // |
2 | // Optional.h |
3 | // |
4 | // Library: Foundation |
5 | // Package: Core |
6 | // Module: Optional |
7 | // |
8 | // Definition of the Optional class template. |
9 | // |
10 | // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. |
11 | // and Contributors. |
12 | // |
13 | // SPDX-License-Identifier: BSL-1.0 |
14 | // |
15 | |
16 | |
17 | #ifndef Foundation_Optional_INCLUDED |
18 | #define Foundation_Optional_INCLUDED |
19 | |
20 | |
21 | #include "Poco/Foundation.h" |
22 | #include "Poco/Exception.h" |
23 | #include <algorithm> |
24 | |
25 | |
26 | namespace Poco { |
27 | |
28 | |
29 | template <typename C> |
30 | class Optional |
31 | /// Optional is a simple wrapper class for value types |
32 | /// that allows to introduce a specified/unspecified state |
33 | /// to value objects. |
34 | /// |
35 | /// An Optional can be default constructed. In this case, |
36 | /// the Optional will have a Null value and isSpecified() will |
37 | /// return false. Calling value()(without default value) on |
38 | /// a Null object will throw a NullValueException. |
39 | /// |
40 | /// An Optional can also be constructed from a value. |
41 | /// It is possible to assign a value to an Optional, and |
42 | /// to reset an Optional to contain a Null value by calling |
43 | /// clear(). |
44 | /// |
45 | /// For use with Optional, the value type should support |
46 | /// default construction. |
47 | /// |
48 | /// Note that the Optional class is basically the same as |
49 | /// Nullable. However, serializers may treat Nullable |
50 | /// and Optional differently. An example is XML serialization based |
51 | /// on XML Schema, where Optional would be used for an element with |
52 | /// minOccurs == 0, whereas Nullable would be used on an element with |
53 | /// nillable == true. |
54 | { |
55 | public: |
56 | Optional(): |
57 | /// Creates an empty Optional. |
58 | _value(), |
59 | _isSpecified(false) |
60 | { |
61 | } |
62 | |
63 | Optional(const C& value): |
64 | /// Creates a Optional with the given value. |
65 | _value(value), |
66 | _isSpecified(true) |
67 | { |
68 | } |
69 | |
70 | Optional(const Optional& other): |
71 | /// Creates a Optional by copying another one. |
72 | _value(other._value), |
73 | _isSpecified(other._isSpecified) |
74 | { |
75 | } |
76 | |
77 | ~Optional() |
78 | /// Destroys the Optional. |
79 | { |
80 | } |
81 | |
82 | Optional& assign(const C& value) |
83 | /// Assigns a value to the Optional. |
84 | { |
85 | _value = value; |
86 | _isSpecified = true; |
87 | return *this; |
88 | } |
89 | |
90 | Optional& assign(const Optional& other) |
91 | /// Assigns another Optional. |
92 | { |
93 | Optional tmp(other); |
94 | swap(tmp); |
95 | return *this; |
96 | } |
97 | |
98 | Optional& operator = (const C& value) |
99 | { |
100 | return assign(value); |
101 | } |
102 | |
103 | Optional& operator = (const Optional& other) |
104 | { |
105 | return assign(other); |
106 | } |
107 | |
108 | void swap(Optional& other) |
109 | { |
110 | std::swap(_value, other._value); |
111 | std::swap(_isSpecified, other._isSpecified); |
112 | } |
113 | |
114 | const C& value() const |
115 | /// Returns the Optional's value. |
116 | /// |
117 | /// Throws a Poco::NullValueException if the value has not been specified. |
118 | { |
119 | if (_isSpecified) |
120 | return _value; |
121 | else |
122 | throw Poco::NullValueException(); |
123 | } |
124 | |
125 | const C& value(const C& deflt) const |
126 | /// Returns the Optional's value, or the |
127 | /// given default value if the Optional's |
128 | /// value has not been specified. |
129 | { |
130 | return _isSpecified ? _value : deflt; |
131 | } |
132 | |
133 | bool isSpecified() const |
134 | /// Returns true iff the Optional's value has been specified. |
135 | { |
136 | return _isSpecified; |
137 | } |
138 | |
139 | void clear() |
140 | /// Clears the Optional. |
141 | { |
142 | _isSpecified = false; |
143 | } |
144 | |
145 | private: |
146 | C _value; |
147 | bool _isSpecified; |
148 | }; |
149 | |
150 | |
151 | template <typename C> |
152 | inline void swap(Optional<C>& n1, Optional<C>& n2) |
153 | { |
154 | n1.swap(n2); |
155 | } |
156 | |
157 | |
158 | } // namespace Poco |
159 | |
160 | |
161 | #endif // Foundation_Optional_INCLUDED |
162 | |