zpp
Zephyr C++20 Framework
result.hpp
Go to the documentation of this file.
1 
7 #ifndef ZPP_INCLUDE_ZPP_RESULT_HPP
8 #define ZPP_INCLUDE_ZPP_RESULT_HPP
9 
10 #include <zephyr/kernel.h>
11 #include <zephyr/sys/__assert.h>
12 
13 #include <zpp/error_code.hpp>
14 
15 #include <utility>
16 
17 namespace zpp {
18 
24 template<typename T_Error>
25 class error_result {
26  static_assert(!std::is_void_v<T_Error>);
27  static_assert(std::is_copy_constructible_v<T_Error>);
28  static_assert(std::is_move_constructible_v<T_Error>);
29  static_assert(std::is_copy_assignable_v<T_Error>);
30  static_assert(std::is_move_assignable_v<T_Error>);
31 public:
32  error_result() noexcept = delete;
33 
34  error_result(error_result&&) noexcept = default;
35  error_result(const error_result&) noexcept = default;
36  error_result& operator=(error_result&&) noexcept = default;
37  error_result& operator=(const error_result&) noexcept = default;
38 
44  explicit error_result(const T_Error& rhs) noexcept
45  : m_error(rhs)
46  {
47  }
48 
54  explicit error_result(T_Error&& rhs) noexcept
55  : m_error(std::move(rhs))
56  {
57  }
58 
64  T_Error& error() noexcept {
65  return m_error;
66  }
67 
73  const T_Error& error() const noexcept {
74  return m_error;
75  }
76 private:
77  T_Error m_error;
78 };
79 
88 template<typename T_Ok, typename T_Error>
89 class result {
90  static_assert(!std::is_void_v<T_Ok>);
91  static_assert(std::is_copy_constructible_v<T_Ok>);
92  static_assert(std::is_move_constructible_v<T_Ok>);
93  static_assert(std::is_copy_assignable_v<T_Ok>);
94  static_assert(std::is_move_assignable_v<T_Ok>);
95 
96  static_assert(!std::is_void_v<T_Error>);
97  static_assert(std::is_copy_constructible_v<T_Error>);
98  static_assert(std::is_move_constructible_v<T_Error>);
99  static_assert(std::is_copy_assignable_v<T_Error>);
100  static_assert(std::is_move_assignable_v<T_Error>);
101 public:
105  result() noexcept
106  : m_is_ok(false)
107  {
108  new(&m_error_value) T_Error();
109  }
110 
116  result(const T_Ok& rhs) noexcept
117  : m_is_ok(true)
118  {
119  new(&m_ok_value) T_Ok(rhs);
120  }
121 
127  result(T_Ok&& rhs) noexcept
128  : m_is_ok(true)
129  {
130  new(&m_ok_value) T_Ok(std::move(rhs));
131  }
132 
138  result(const error_result<T_Error>& rhs) noexcept
139  : m_is_ok(false)
140  {
141  new(&m_error_value) T_Error(rhs.error());
142  }
143 
144 
151  : m_is_ok(false)
152  {
153  new(&m_error_value) T_Error(std::move(rhs.error()));
154  }
155 
161  result(const result& rhs) noexcept
162  : m_is_ok(rhs.m_is_ok)
163  {
164  if (m_is_ok) {
165  new(&m_ok_value) T_Ok(rhs.m_ok_value);
166  } else {
167  new(&m_error_value) T_Error(rhs.m_error_value);
168  }
169  }
170 
176  result(result&& rhs) noexcept
177  : m_is_ok(rhs.m_is_ok)
178  {
179  if (m_is_ok) {
180  new(&m_ok_value) T_Ok(std::move(rhs.m_ok_value));
181  } else {
182  new(&m_error_value) T_Error(std::move(rhs.m_error_value));
183  }
184  }
185 
189  ~result() noexcept {
190  if (m_is_ok) {
191  m_ok_value.~T_Ok();
192  } else {
193  m_error_value.~T_Error();
194  }
195  }
196 
197  void assign_value(const T_Ok& v) noexcept {
198  if (m_is_ok) {
199  m_ok_value.~T_Ok();
200  } else {
201  m_error_value.~T_Error();
202  }
203 
204  m_is_ok = true;
205  new(&m_ok_value) T_Ok(v);
206  }
207 
208  void assign_value(T_Ok&& v) noexcept {
209  if (m_is_ok) {
210  m_ok_value.~T_Ok();
211  } else {
212  m_error_value.~T_Error();
213  }
214 
215  m_is_ok = true;
216  new(&m_ok_value) T_Ok(std::move(v));
217  }
218 
219  void assign_error(const T_Error& e) noexcept {
220  if (m_is_ok) {
221  m_ok_value.~T_Ok();
222  } else {
223  m_error_value.~T_Error();
224  }
225 
226  m_is_ok = false;
227  new(&m_error_value) T_Error(e);
228  }
229 
230  void assign_error(T_Error&& e) noexcept {
231  if (m_is_ok) {
232  m_ok_value.~T_Ok();
233  } else {
234  m_error_value.~T_Error();
235  }
236 
237  m_is_ok = false;
238  new(&m_error_value) T_Error(std::move(e));
239  }
240 
241 
247  result& operator=(const result& rhs) noexcept
248  {
249  if (rhs.m_is_ok) {
250  assign_value(rhs.m_ok_value);
251  } else {
252  assign_error(rhs.m_error_value);
253  }
254 
255  return *this;
256  }
257 
263  result& operator=(result&& rhs) noexcept
264  {
265  if (rhs.m_is_ok) {
266  assign_value(std::move(rhs.m_ok_value));
267  } else {
268  assign_error(std::move(rhs.m_error_value));
269  }
270 
271  return *this;
272  }
273 
274 
280  result& operator=(const T_Ok& rhs) noexcept
281  {
282  assign_value(rhs);
283  return *this;
284  }
285 
291  result& operator=(T_Ok&& rhs) noexcept
292  {
293  assign_value(std::move(rhs));
294  return *this;
295  }
296 
302  result& operator=(const error_result<T_Error>& rhs) noexcept
303  {
304  assign_error(rhs.error());
305  return *this;
306  }
307 
314  {
315  assign_error(std::move(rhs.error()));
316  return *this;
317  }
318 
319 
327  T_Ok& value() noexcept {
328  if (!m_is_ok) {
329  // unhandeld error
330  }
331 
332  return m_ok_value;
333  }
334 
342  const T_Ok& value() const noexcept {
343  if (!m_is_ok) {
344  // unhandeld error
345  }
346 
347  return m_ok_value;
348  }
349 
350 
358  T_Error& error() noexcept {
359  if (m_is_ok) {
360  // unhandeld error
361  }
362 
363  return m_error_value;
364  }
365 
373  const T_Error& error() const noexcept {
374  if (m_is_ok) {
375  // unhandeld error
376  }
377 
378  return m_error_value;
379  }
380 
388  T_Ok& operator*() noexcept {
389  return value();
390  }
391 
399  const T_Ok& operator*() const noexcept {
400  return value();
401  }
402 
410  T_Ok* operator->() noexcept {
411  if (!m_is_ok) {
412  // unhandeld error
413  }
414 
415  return &m_ok_value;
416  }
417 
425  const T_Ok* operator->() const noexcept {
426  if (!m_is_ok) {
427  // unhandeld error
428  }
429 
430  return &m_ok_value;
431  }
432 
438  constexpr bool has_value() const noexcept {
439  return m_is_ok;
440  }
441 
447  constexpr explicit operator bool() const noexcept {
448  return m_is_ok;
449  }
450 private:
451  bool m_is_ok{false};
452  union {
453  T_Error m_error_value;
455  };
456 };
457 
466 template<typename T_Error>
467 class result<void, T_Error> {
468  static_assert(!std::is_void_v<T_Error>);
469  static_assert(std::is_copy_constructible_v<T_Error>);
470  static_assert(std::is_move_constructible_v<T_Error>);
471  static_assert(std::is_copy_assignable_v<T_Error>);
472  static_assert(std::is_move_assignable_v<T_Error>);
473 public:
477  result() noexcept = default;
478 
484  result(const error_result<T_Error>& rhs) noexcept
485  : m_is_ok(false)
486  , m_error_value( rhs.error() )
487  {
488  }
489 
491  : m_is_ok(false)
492  , m_error_value( std::move(rhs.error()) )
493  {
494  }
495 
501  result(const result& rhs) noexcept = default;
502 
508  result(result&& rhs) noexcept = default;
509 
513  ~result() noexcept = default;
514 
520  result& operator=(const result& rhs) noexcept = default;
521 
527  result& operator=(result&& rhs) noexcept = default;
528 
529 
530  void assign_value() noexcept {
531  m_is_ok = true;
532  }
533 
534  void assign_error(const T_Error& e) noexcept {
535  m_is_ok = false;
536  m_error_value = T_Error(e);
537  }
538 
539  void assign_error(T_Error&& e) noexcept {
540  m_is_ok = false;
541  m_error_value = T_Error(std::move(e));
542  }
543 
549  result& operator=(const error_result<T_Error>& rhs) noexcept
550  {
551  assign_error(rhs.error());
552  return *this;
553  }
554 
561  {
562  assign_error(std::move(rhs.error()));
563  return *this;
564  }
565 
573  void value() noexcept {
574  if (!m_is_ok) {
575  // unhandeld error
576  }
577  }
578 
586  void value() const noexcept {
587  if (!m_is_ok) {
588  // unhandeld error
589  }
590  }
591 
599  T_Error& error() noexcept {
600  if (m_is_ok) {
601  // unhandeld error
602  }
603 
604  return m_error_value;
605  }
606 
614  const T_Error& error() const noexcept {
615  if (m_is_ok) {
616  // unhandeld error
617  }
618 
619  return m_error_value;
620  }
621 
627  constexpr bool has_value() const noexcept {
628  return m_is_ok;
629  }
630 
636  constexpr explicit operator bool() const noexcept {
637  return m_is_ok;
638  }
639 private:
640  bool m_is_ok{false};
641  T_Error m_error_value;
642 };
643 
645 
654 template<typename T_Ok, typename T_Error>
655 constexpr bool operator==(const result<T_Ok, T_Error>& lhs, bool rhs) noexcept {
656  return bool(lhs) == bool(rhs);
657 }
658 
667 template<typename T_Ok, typename T_Error>
668 constexpr bool operator==(bool lhs, const result<T_Ok, T_Error>& rhs) noexcept {
669  return bool(lhs) == bool(rhs);
670 }
671 
680 template<typename T_Ok, typename T_Error>
681 constexpr bool operator!=(const result<T_Ok, T_Error>& lhs, bool rhs) noexcept {
682  return bool(lhs) != bool(rhs);
683 }
684 
693 template<typename T_Ok, typename T_Error>
694 constexpr bool operator!=(bool lhs, const result<T_Ok, T_Error>& rhs) noexcept {
695  return bool(lhs) != bool(rhs);
696 }
697 
698 } // namespace zpp
699 
700 #endif // ZPP_INCLUDE_ZPP_RESULT_HPP
helper class for error result
Definition: result.hpp:25
T_Error & error() noexcept
return error value
Definition: result.hpp:64
const T_Error & error() const noexcept
return error value
Definition: result.hpp:73
error_result() noexcept=delete
error_result(T_Error &&rhs) noexcept
initialize error_result
Definition: result.hpp:54
result(const result &rhs) noexcept=default
copy contructor
result() noexcept=default
default initialization to error state
void assign_error(const T_Error &e) noexcept
Definition: result.hpp:534
constexpr bool has_value() const noexcept
convert the result to a bool
Definition: result.hpp:627
const T_Error & error() const noexcept
return a const reference to the result value
Definition: result.hpp:614
result(error_result< T_Error > &&rhs) noexcept
Definition: result.hpp:490
void value() const noexcept
return a const reference to the result value
Definition: result.hpp:586
T_Error & error() noexcept
return a reference to the OK value
Definition: result.hpp:599
void assign_error(T_Error &&e) noexcept
Definition: result.hpp:539
void value() noexcept
return a reference to the OK value
Definition: result.hpp:573
result(result &&rhs) noexcept=default
move contructor
result & operator=(const error_result< T_Error > &rhs) noexcept
copy operator
Definition: result.hpp:549
result & operator=(error_result< T_Error > &&rhs) noexcept
move operator
Definition: result.hpp:560
~result() noexcept=default
destructor
result class
Definition: result.hpp:89
result(const error_result< T_Error > &rhs) noexcept
initialization to error state
Definition: result.hpp:138
T_Ok * operator->() noexcept
return a pointer to the result value
Definition: result.hpp:410
result(result &&rhs) noexcept
move contructor
Definition: result.hpp:176
void assign_value(T_Ok &&v) noexcept
Definition: result.hpp:208
constexpr bool has_value() const noexcept
convert the result to a bool
Definition: result.hpp:438
result() noexcept
default initialization to error state
Definition: result.hpp:105
result(error_result< T_Error > &&rhs) noexcept
initialization to error state
Definition: result.hpp:150
void assign_value(const T_Ok &v) noexcept
Definition: result.hpp:197
const T_Ok * operator->() const noexcept
return a const pointer to the result value
Definition: result.hpp:425
T_Ok m_ok_value
Definition: result.hpp:454
result(T_Ok &&rhs) noexcept
initialization to OK state
Definition: result.hpp:127
T_Ok & value() noexcept
return a reference to the OK value
Definition: result.hpp:327
const T_Error & error() const noexcept
return a const reference to the result value
Definition: result.hpp:373
~result() noexcept
destructor
Definition: result.hpp:189
result & operator=(error_result< T_Error > &&rhs) noexcept
move operator
Definition: result.hpp:313
result & operator=(const result &rhs) noexcept
copy operator
Definition: result.hpp:247
void assign_error(T_Error &&e) noexcept
Definition: result.hpp:230
T_Error m_error_value
Definition: result.hpp:453
void assign_error(const T_Error &e) noexcept
Definition: result.hpp:219
result & operator=(T_Ok &&rhs) noexcept
move operator
Definition: result.hpp:291
T_Ok & operator*() noexcept
return a reference to the result value
Definition: result.hpp:388
const T_Ok & value() const noexcept
return a const reference to the result value
Definition: result.hpp:342
result(const T_Ok &rhs) noexcept
initialization to OK state
Definition: result.hpp:116
result & operator=(const T_Ok &rhs) noexcept
copy operator
Definition: result.hpp:280
T_Error & error() noexcept
return a reference to the OK value
Definition: result.hpp:358
const T_Ok & operator*() const noexcept
return a const reference to the result value
Definition: result.hpp:399
result(const result &rhs) noexcept
copy contructor
Definition: result.hpp:161
result & operator=(const error_result< T_Error > &rhs) noexcept
copy operator
Definition: result.hpp:302
result & operator=(result &&rhs) noexcept
move operator
Definition: result.hpp:263
constexpr bool operator==(const result< T_Ok, T_Error > &lhs, bool rhs) noexcept
compare result with bool
Definition: result.hpp:655
constexpr bool operator!=(const result< T_Ok, T_Error > &lhs, bool rhs) noexcept
compare result with bool
Definition: result.hpp:681