Nullable.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. //
  2. // Nullable.h
  3. //
  4. // $Id: //poco/1.4/Foundation/include/Poco/Nullable.h#1 $
  5. //
  6. // Library: Foundation
  7. // Package: Core
  8. // Module: Nullable
  9. //
  10. // Definition of the Nullable template class.
  11. //
  12. // Copyright (c) 2010, Applied Informatics Software Engineering GmbH.
  13. // and Contributors.
  14. //
  15. // SPDX-License-Identifier: BSL-1.0
  16. //
  17. #ifndef Foundation_Nullable_INCLUDED
  18. #define Foundation_Nullable_INCLUDED
  19. #include "Poco/Foundation.h"
  20. #include "Poco/Exception.h"
  21. #include <algorithm>
  22. #include <iostream>
  23. namespace Poco {
  24. enum NullType
  25. {
  26. NULL_GENERIC = 0
  27. };
  28. template <typename C>
  29. class Nullable
  30. /// Nullable is a simple wrapper class for value types
  31. /// that allows objects or native type variables
  32. /// to have "null" value.
  33. ///
  34. /// The class is useful for passing parameters to functions
  35. /// when parameters are optional and no default values
  36. /// should be used or when a non-assigned state is needed,
  37. /// such as in e.g. fetching null values from database.
  38. ///
  39. /// A Nullable can be default constructed. In this case,
  40. /// the Nullable will have a Null value and isNull() will
  41. /// return true. Calling value() (without default value) on
  42. /// a Null object will throw a NullValueException.
  43. ///
  44. /// A Nullable can also be constructed from a value.
  45. /// It is possible to assign a value to a Nullable, and
  46. /// to reset a Nullable to contain a Null value by calling
  47. /// clear().
  48. ///
  49. /// For use with Nullable, the value type should support
  50. /// default construction.
  51. {
  52. public:
  53. Nullable():
  54. /// Creates an empty Nullable.
  55. _value(),
  56. _isNull(true)
  57. {
  58. }
  59. Nullable(const NullType&):
  60. /// Creates an empty Nullable.
  61. _value(),
  62. _isNull(true)
  63. {
  64. }
  65. Nullable(const C& value):
  66. /// Creates a Nullable with the given value.
  67. _value(value),
  68. _isNull(false)
  69. {
  70. }
  71. Nullable(const Nullable& other):
  72. /// Creates a Nullable by copying another one.
  73. _value(other._value),
  74. _isNull(other._isNull)
  75. {
  76. }
  77. ~Nullable()
  78. /// Destroys the Nullable.
  79. {
  80. }
  81. Nullable& assign(const C& value)
  82. /// Assigns a value to the Nullable.
  83. {
  84. _value = value;
  85. _isNull = false;
  86. return *this;
  87. }
  88. Nullable& assign(const Nullable& other)
  89. /// Assigns another Nullable.
  90. {
  91. Nullable tmp(other);
  92. swap(tmp);
  93. return *this;
  94. }
  95. Nullable& assign(NullType)
  96. /// Sets value to null.
  97. {
  98. _isNull = true;
  99. return *this;
  100. }
  101. Nullable& operator = (const C& value)
  102. /// Assigns a value to the Nullable.
  103. {
  104. return assign(value);
  105. }
  106. Nullable& operator = (const Nullable& other)
  107. /// Assigns another Nullable.
  108. {
  109. return assign(other);
  110. }
  111. Nullable& operator = (NullType)
  112. /// Assigns another Nullable.
  113. {
  114. _isNull = true;
  115. return *this;
  116. }
  117. void swap(Nullable& other)
  118. /// Swaps this Nullable with other.
  119. {
  120. std::swap(_value, other._value);
  121. std::swap(_isNull, other._isNull);
  122. }
  123. bool operator == (const Nullable<C>& other) const
  124. /// Compares two Nullables for equality
  125. {
  126. return (_isNull && other._isNull) || (_isNull == other._isNull && _value == other._value);
  127. }
  128. bool operator == (const C& value) const
  129. /// Compares Nullable with value for equality
  130. {
  131. return (!_isNull && _value == value);
  132. }
  133. bool operator == (const NullType&) const
  134. /// Compares Nullable with NullData for equality
  135. {
  136. return _isNull;
  137. }
  138. bool operator != (const C& value) const
  139. /// Compares Nullable with value for non equality
  140. {
  141. return !(*this == value);
  142. }
  143. bool operator != (const Nullable<C>& other) const
  144. /// Compares two Nullables for non equality
  145. {
  146. return !(*this == other);
  147. }
  148. bool operator != (const NullType&) const
  149. /// Compares with NullData for non equality
  150. {
  151. return !_isNull;
  152. }
  153. bool operator < (const Nullable<C>& other) const
  154. /// Compares two Nullable objects. Return true if this object's
  155. /// value is smaler than the other object's value.
  156. /// Null value is smaller than a non-null value.
  157. {
  158. if (_isNull && other._isNull) return false;
  159. if (!_isNull && !other._isNull)
  160. return (_value < other._value);
  161. if (_isNull && !other._isNull) return true;
  162. return false;
  163. }
  164. bool operator > (const Nullable<C>& other) const
  165. /// Compares two Nullable objects. Return true if this object's
  166. /// value is greater than the other object's value.
  167. /// A non-null value is greater than a null value.
  168. {
  169. return !(*this == other) && !(*this < other);
  170. }
  171. C& value()
  172. /// Returns the Nullable's value.
  173. ///
  174. /// Throws a NullValueException if the Nullable is empty.
  175. {
  176. if (!_isNull)
  177. return _value;
  178. else
  179. throw NullValueException();
  180. }
  181. const C& value() const
  182. /// Returns the Nullable's value.
  183. ///
  184. /// Throws a NullValueException if the Nullable is empty.
  185. {
  186. if (!_isNull)
  187. return _value;
  188. else
  189. throw NullValueException();
  190. }
  191. const C& value(const C& deflt) const
  192. /// Returns the Nullable's value, or the
  193. /// given default value if the Nullable is empty.
  194. {
  195. return _isNull ? deflt : _value;
  196. }
  197. operator C& ()
  198. /// Get reference to the value
  199. {
  200. return value();
  201. }
  202. operator const C& () const
  203. /// Get const reference to the value
  204. {
  205. return value();
  206. }
  207. operator NullType& ()
  208. /// Get reference to the value
  209. {
  210. return _null;
  211. }
  212. bool isNull() const
  213. /// Returns true if the Nullable is empty.
  214. {
  215. return _isNull;
  216. }
  217. void clear()
  218. /// Clears the Nullable.
  219. {
  220. _isNull = true;
  221. }
  222. private:
  223. C _value;
  224. bool _isNull;
  225. NullType _null;
  226. };
  227. template <typename C>
  228. inline void swap(Nullable<C>& n1, Nullable<C>& n2)
  229. {
  230. n1.swap(n2);
  231. }
  232. template <typename C>
  233. std::ostream& operator<<(std::ostream& out, const Nullable<C>& obj)
  234. {
  235. if (!obj.isNull()) out << obj.value();
  236. return out;
  237. }
  238. template <typename C>
  239. bool operator == (const NullType&, const Nullable<C>& n)
  240. /// Returns true if this Nullable is null.
  241. {
  242. return n.isNull();
  243. }
  244. template <typename C>
  245. bool operator != (const C& c, const Nullable<C>& n)
  246. /// Compares Nullable with value for non equality
  247. {
  248. return !(n == c);
  249. }
  250. template <typename C>
  251. bool operator == (const C& c, const Nullable<C>& n)
  252. /// Compares Nullable with NullData for equality
  253. {
  254. return (n == c);
  255. }
  256. template <typename C>
  257. bool operator != (const NullType&, const Nullable<C>& n)
  258. /// Returns true if this Nullable is not null.
  259. {
  260. return !n.isNull();
  261. }
  262. } // namespace Poco
  263. #endif // Foundation_Nullable_INCLUDED