ledger-core
Option.hpp
1 /*
2  *
3  * Option
4  * ledger-core
5  *
6  * Created by Pierre Pollastri on 20/01/2017.
7  *
8  * The MIT License (MIT)
9  *
10  * Copyright (c) 2016 Ledger
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a copy
13  * of this software and associated documentation files (the "Software"), to deal
14  * in the Software without restriction, including without limitation the rights
15  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16  * copies of the Software, and to permit persons to whom the Software is
17  * furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included in all
20  * copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28  * SOFTWARE.
29  *
30  */
31 #ifndef LEDGER_CORE_OPTION_HPP
32 #define LEDGER_CORE_OPTION_HPP
33 
34 #include "optional.hpp"
35 #include "Unit.hpp"
36 #include <cstddef>
37 #include <new>
38 #include <stdexcept>
39 #include <type_traits>
40 #include <utility>
41 #include <vector>
42 #include <memory>
43 
44 #undef foreach
45 
46 namespace ledger {
47  namespace core {
48  template <typename T>
49  class Option {
50  static_assert(!std::is_reference<T>::value,
51  "Option is not compatible with references");
52  static_assert(!std::is_abstract<T>::value,
53  "Option is not compatible with abstract types");
54  public:
55  typedef T BaseType;
56  static const Option<T> NONE;
57 
58  Option() {};
59  Option(const T& value) : _optional(value) {};
60  Option(T&& value) : _optional(std::move(value)) {};
61 
62  Option(const Option<T>& option) : _optional(option._optional) {};
63 
64  Option(Option<T>&& option) : _optional(std::move(option._optional)) {}
65 
66  Option(const std::experimental::optional<T>& optional) : _optional(optional) {};
67  Option<T>& operator=(const Option<T>& option) {
68  if (this != &option) {
69  _optional = option._optional;
70  }
71  return *this;
72  };
73 
74  Option<T>& operator=(Option<T>&& option) {
75  if (this != &option) {
76  _optional = std::move(option._optional);
77  }
78  return *this;
79  };
80 
81  Option<T>& operator=(const T& v) {
82  _optional = optional<T>(v);
83  return *this;
84  };
85 
86  Option<T>& operator=(T&& v) {
87  _optional = optional<T>(std::move(v));
88  return *this;
89  };
90 
91  Option<T>&operator=(T* v) {
92  if (v == nullptr) {
93  _optional = optional<T>(v);
94  } else {
95  _optional = optional<T>(*v);
96  }
97  return *this;
98  };
99 
100  inline bool isEmpty() const {
101  return !_optional;
102  };
103 
104  inline bool hasValue() const {
105  return !isEmpty();
106  };
107 
108  inline bool nonEmpty() const {
109  return !isEmpty();
110  }
111 
112  T& operator*() & {return *_optional;};
113  const T& operator*() const & { return *_optional;};
114  T&& operator*() && {return std::move(*_optional);};
115  const T&& operator*() const && { return std::move(*_optional);};
116 
117  const T* operator->() const {
118  return &_optional.value();
119  }
120 
121  T* operator->() {
122  return &_optional.value();
123  }
124 
125  T& getValue() & {
126  return _optional.value();
127  }
128 
129  const T& getValue() const & {
130  return _optional.value();
131  }
132 
133  T&& getValue() && {
134  return std::move(_optional.value());
135  }
136 
137  const T&& getValue() const && {
138  return std::move(_optional.value());
139  }
140 
141  T getValueOr(const T& v) const& {
142  if (isEmpty())
143  return v;
144  else
145  return getValue();
146  }
147 
148  T getOrElse(std::function<T ()> f) const {
149  if (isEmpty())
150  return f();
151  else
152  return getValue();
153  }
154 
155  T getValueOr(T&& v) const & {
156  if (isEmpty())
157  return std::forward<T>(v);
158  return getValue();
159  }
160 
161  T getValueOr(T&& v) && {
162  if (isEmpty())
163  return std::move(v);
164  return getValue();
165  }
166 
167  optional<T> toOptional() const {
168  return _optional;
169  };
170 
171  bool operator==(const T& v) const noexcept {
172  return hasValue() && **this == v;
173  }
174 
175  bool operator==(const Option<T>& v) const noexcept {
176  return (isEmpty() == v.isEmpty()) || (hasValue() && v.hasValue() && **this == *v);
177  }
178 
179  bool operator!=(const T& v) const noexcept {
180  return !(*this == v);
181  }
182 
183  bool operator!=(const Option<T>& v) const noexcept {
184  return !(*this == v);
185  }
186 
187  operator bool() const { return hasValue();};
188 
189  void foreach(std::function<void (const T& value)> f) const {
190  if (hasValue()) {
191  f(_optional.value());
192  }
193  }
194 
195  bool forall(std::function<bool (const T& value)> f) const {
196  if (hasValue()) {
197  return f(_optional.value());
198  }
199  return false;
200  }
201 
202  template <typename A>
203  Option<A> map(std::function<A (const T&)> f) const {
204  if (isEmpty())
205  return Option<A>();
206  return Option<A>(f(getValue()));
207  };
208 
209  template <typename A>
210  Option<A> flatMap(std::function<Option<A> (const T&)> f) const {
211  if (isEmpty())
212  return Option<A>();
213  return f(getValue());
214  }
215 
216  std::vector<T> toVector() const {
217  if (isEmpty())
218  return std::vector<T>();
219  std::vector<T> out;
220  out.push_back(getValue());
221  return out;
222  }
223 
224  template <typename A>
225  Option<A> orElse(std::function<Option<A> ()> f) const {
226  if (isEmpty()) {
227  return f();
228  } else {
229  return Option<A>::NONE;
230  }
231  }
232 
233  operator optional<T>() {
234  return _optional;
235  }
236 
237  private:
238  optional<T> _optional;
239  };
240 
241  template <typename T>
243 
244  template <typename T>
246 
247  template <typename T>
248  Option<std::shared_ptr<T>> make_option(const std::shared_ptr<T>& ptr) {
249  if (ptr == nullptr)
250  return Option<std::shared_ptr<T>>();
251  else
252  return Option<std::shared_ptr<T>>(ptr);
253  }
254 
255  }
256 }
257 
258 #endif //LEDGER_CORE_OPTION_HPP
Definition: Option.hpp:49
Definition: Account.cpp:8
Definition: optional.hpp:177