My Project
result.hpp
Go to the documentation of this file.
1 
28 #ifndef BSL_RESULT_HPP
29 #define BSL_RESULT_HPP
30 
31 #include "construct_at.hpp"
32 #include "cstdint.hpp"
33 #include "debug.hpp"
34 #include "destroy_at.hpp"
35 #include "errc_type.hpp"
36 #include "in_place.hpp"
43 #include "is_nothrow_swappable.hpp"
44 #include "is_same.hpp"
45 #include "move.hpp"
46 #include "source_location.hpp"
47 #include "swap.hpp"
48 
49 namespace bsl
50 {
51  namespace details
52  {
59  enum class result_type : bsl::uint8
60  {
61  contains_t,
62  contains_e
63  };
64  }
65 
77  template<typename T, typename E = errc_type>
78  class result final
79  {
80  static_assert(!is_same<T, E>::value);
83  static_assert(is_nothrow_destructible<E>::value);
86 
94  static constexpr void
95  private_swap(result &lhs, result &rhs) noexcept
96  {
97  if (details::result_type::contains_t == lhs.m_which) {
98  if (details::result_type::contains_t == rhs.m_which) {
99  bsl::swap(lhs.m_t, rhs.m_t); // NOLINT
100  }
101  else {
102  E tmp_e{bsl::move(rhs.m_e)}; // NOLINT
103  destroy_at(&rhs.m_e); // NOLINT
104  construct_at<T>(&rhs.m_t, bsl::move(lhs.m_t)); // NOLINT
105  destroy_at(&lhs.m_t); // NOLINT
106  construct_at<E>(&lhs.m_e, bsl::move(tmp_e)); // NOLINT
107  }
108  }
109  else {
110  if (details::result_type::contains_t == rhs.m_which) {
111  E tmp_e{bsl::move(lhs.m_e)}; // NOLINT
112  destroy_at(&lhs.m_e); // NOLINT
113  construct_at<T>(&lhs.m_t, bsl::move(rhs.m_t)); // NOLINT
114  destroy_at(&rhs.m_t); // NOLINT
115  construct_at<E>(&rhs.m_e, bsl::move(tmp_e)); // NOLINT
116  }
117  else {
118  bsl::swap(lhs.m_e, rhs.m_e); // NOLINT
119  }
120  }
121 
122  bsl::swap(lhs.m_which, rhs.m_which);
123  }
124 
125  public:
127  using type = T;
128 
148  constexpr result(T const &t) noexcept( // PRQA S 2180 // NOLINT
150  : m_which{details::result_type::contains_t}, m_t{t}
151  {}
152 
172  constexpr result(T &&t) noexcept( // PRQA S 2180 // NOLINT
174  : m_which{details::result_type::contains_t}, m_t{bsl::move(t)}
175  {}
176 
189  template<typename... ARGS>
190  constexpr result( // NOLINT
191  bsl::in_place_t const &ip,
192  ARGS &&... args) noexcept(is_nothrow_constructible<T, ARGS...>::value)
193  : m_which{details::result_type::contains_t}, m_t{bsl::forward<ARGS>(args)...}
194  {
195  bsl::discard(ip);
196  }
197 
213  constexpr result( // PRQA S 2180 // NOLINT
214  E const &e,
215  sloc_type const &sloc = here()) noexcept
216  : m_which{details::result_type::contains_e}, m_e{e}
217  {
218  bsl::error() << e.message() << bsl::endl;
219  bsl::error() << sloc;
220  }
221 
237  constexpr result( // PRQA S 2180 // NOLINT
238  E &&e,
239  sloc_type const &sloc = here()) noexcept
240  : m_which{details::result_type::contains_e}, m_e{bsl::move(e)}
241  {
242  bsl::error() << e.message() << bsl::endl;
243  bsl::error() << sloc;
244  }
245 
255  BSL_CONSTEXPR ~result() noexcept(is_nothrow_destructible<T>::value)
256  {
257  if (details::result_type::contains_t == m_which) {
258  destroy_at(&m_t); // NOLINT
259  }
260  else {
261  destroy_at(&m_e); // NOLINT
262  }
263  }
264 
291  constexpr result(result const &o) noexcept( // PRQA S 4285
293  : m_which{o.m_which} // PRQA S 4050
294  {
295  if (details::result_type::contains_t == m_which) {
296  construct_at<T>(&m_t, o.m_t); // NOLINT
297  }
298  else {
299  construct_at<E>(&m_e, o.m_e); // NOLINT
300  }
301  }
302 
329  constexpr result(result &&o) noexcept( // PRQA S 4285
331  : m_which{o.m_which} // PRQA S 4050
332  {
333  if (details::result_type::contains_t == m_which) {
334  construct_at<T>(&m_t, bsl::move(o.m_t)); // NOLINT
335  }
336  else {
337  construct_at<E>(&m_e, bsl::move(o.m_e)); // NOLINT
338  }
339  }
340 
353  constexpr result &
354  operator=(result const &o) &noexcept(
356  {
357  result tmp{o};
358  private_swap(*this, tmp);
359  return *this;
360  }
361 
374  constexpr result &
375  operator=(result &&o) &noexcept(
377  {
378  result tmp{bsl::move(o)};
379  private_swap(*this, tmp);
380  return *this;
381  }
382 
398  template<typename O>
399  constexpr result(O val) noexcept = delete; // PRQA S 2180
400 
419  [[nodiscard]] constexpr T *
420  get_if() &noexcept
421  {
422  if (details::result_type::contains_t == m_which) {
423  return &m_t; // PRQA S 4024 // NOLINT
424  }
425 
426  return nullptr;
427  }
428 
437  [[nodiscard]] constexpr T *get_if() &&noexcept = delete;
438 
448  [[nodiscard]] constexpr T const *
449  get_if() const &noexcept
450  {
451  if (details::result_type::contains_t == m_which) {
452  return &m_t; // NOLINT
453  }
454 
455  return nullptr;
456  }
457 
466  [[nodiscard]] constexpr T const *get_if() const &&noexcept = delete;
467 
478  [[nodiscard]] constexpr E
479  errc(E const &fallback = E{}) const noexcept
480  {
481  if (details::result_type::contains_e == m_which) {
482  return m_e; // NOLINT
483  }
484 
485  return fallback;
486  }
487 
499  [[nodiscard]] constexpr bool
500  success() const noexcept
501  {
502  return details::result_type::contains_t == m_which;
503  }
504 
516  [[nodiscard]] constexpr bool
517  failure() const noexcept
518  {
519  return details::result_type::contains_e == m_which;
520  }
521 
522  private:
524  details::result_type m_which;
525 
539  union // PRQA S 2176, 2026, 2177
540  {
542  T m_t;
544  E m_e;
545  };
546  };
547 
558  template<typename T, typename E>
559  constexpr bool
560  operator==(result<T, E> const &lhs, result<T, E> const &rhs) noexcept
561  {
562  if (lhs.success() != rhs.success()) {
563  return false;
564  }
565 
566  if (lhs.success()) {
567  return *lhs.get_if() == *rhs.get_if();
568  }
569 
570  return lhs.errc() == rhs.errc();
571  }
572 
583  template<typename T, typename E>
584  constexpr bool
585  operator!=(result<T, E> const &lhs, result<T, E> const &rhs) noexcept
586  {
587  return !(lhs == rhs);
588  }
589 }
590 
591 #endif
constexpr bool operator!=(result< T, E > const &lhs, result< T, E > const &rhs) noexcept
Returns false if the lhs is equal to the rhs, true otherwise.
Definition: result.hpp:585
::uint8_t uint8
defines an 8bit unsigned integer
Definition: cstdint.hpp:45
If the provided type T is nothrow swappable, provides the member constant value equal to true....
Definition: is_nothrow_swappable.hpp:49
constexpr bool operator==(result< T, E > const &lhs, result< T, E > const &rhs) noexcept
Returns true if the lhs is equal to the rhs, false otherwise.
Definition: result.hpp:560
If the provided type is nothrow move assignable, provides the member constant value equal to true....
Definition: is_nothrow_move_assignable.hpp:49
constexpr result(bsl::in_place_t const &ip, ARGS &&... args) noexcept(is_nothrow_constructible< T, ARGS... >::value)
Constructs a bsl::result that contains T by constructing T in place.
Definition: result.hpp:190
BSL_CONSTEXPR ~result() noexcept(is_nothrow_destructible< T >::value)
Destroyes a previously created bsl::result. Since we require E to be trivially destructible,...
Definition: result.hpp:255
constexpr result(E &&e, sloc_type const &sloc=here()) noexcept
Constructs a bsl::result that contains E, by moving "e".
Definition: result.hpp:237
constexpr bool failure() const noexcept
Returns true if the bsl::result contains E, otherwise, if the bsl::result contains T,...
Definition: result.hpp:517
constexpr void destroy_at(T *const ptr) noexcept(noexcept(ptr->T::~T()))
Calls the destructor of the object pointed to by ptr.
Definition: destroy_at.hpp:52
Provides the ability to return T or E from a function, ensuring that T is only created if an error is...
Definition: result.hpp:78
constexpr T * get_if() &noexcept
Returns a handle to T if this object contains T, otherwise it returns a nullptr.
Definition: result.hpp:420
bsl::in_place, bsl::in_place_type, and bsl::in_place_index are disambiguation tags that can be passed...
Definition: in_place.hpp:45
constexpr result & operator=(result const &o) &noexcept(is_nothrow_copy_constructible< T >::value &&is_nothrow_swappable< T >::value)
copy assignment
Definition: result.hpp:354
constexpr result & operator=(result &&o) &noexcept(is_nothrow_move_constructible< T >::value &&is_nothrow_swappable< T >::value)
move assignment
Definition: result.hpp:375
constexpr enable_if_t< is_movable< T >::value > swap(T &lhs, T &rhs) noexcept(is_nothrow_movable< T >::value)
Swaps the given values.
Definition: swap.hpp:54
This class implements the source_location specification that will eventually be included in C++20....
Definition: source_location.hpp:47
constexpr E errc(E const &fallback=E{}) const noexcept
Returns an error code if this object contains E, otherwise it returns "fallback".
Definition: result.hpp:479
constexpr source_location here(source_location const &sloc=source_location::current()) noexcept
This provides a less verbose version of bsl::source_location::current() to help reduce how large this...
Definition: source_location.hpp:185
E m_e
stores an error code when not storing T
Definition: result.hpp:544
If the provided type is nothrow copy constructible, provides the member constant value equal to true....
Definition: is_nothrow_copy_constructible.hpp:49
If the provided types are the same, provides the member constant value equal to true....
Definition: is_same.hpp:48
constexpr void move(fmt< V > &&val) noexcept=delete
Used to prevent a move of bsl::fmt as it must always be a temporary r-value.
If the provided type is nothrow constructible, provides the member constant value equal to true....
Definition: is_nothrow_constructible.hpp:47
constexpr T const * get_if() const &noexcept
Returns a handle to T if this object contains T, otherwise it returns a nullptr.
Definition: result.hpp:449
constexpr result(result &&o) noexcept(//PRQA S 4285 is_nothrow_move_constructible< T >::value)
move constructor
Definition: result.hpp:329
T type
alias for: T
Definition: result.hpp:127
constexpr bool success() const noexcept
Returns true if the bsl::result contains T, otherwise, if the bsl::result contains an error code,...
Definition: result.hpp:500
constexpr result(result const &o) noexcept(//PRQA S 4285 is_nothrow_copy_constructible< T >::value)
copy constructor
Definition: result.hpp:291
If the provided type is nothrow destructible, provides the member constant value equal to true....
Definition: is_nothrow_destructible.hpp:120
constexpr result(E const &e, sloc_type const &sloc=here()) noexcept
Constructs a bsl::result that contains E, by copying "e".
Definition: result.hpp:213
constexpr result(T &&t) noexcept(//PRQA S 2180//NOLINT is_nothrow_move_constructible< T >::value)
Constructs a bsl::result that contains T, by moving "t".
Definition: result.hpp:172
result_type
Defines what a bsl::result is currently storing. This is defined as a bsl::uint8 to ensure it is as s...
Definition: result.hpp:59
If the provided type is nothrow copy assignable, provides the member constant value equal to true....
Definition: is_nothrow_copy_assignable.hpp:49
T m_t
stores T when not storing an error code
Definition: result.hpp:542
constexpr result(T const &t) noexcept(//PRQA S 2180//NOLINT is_nothrow_copy_constructible< T >::value)
Constructs a bsl::result that contains T, by copying "t".
Definition: result.hpp:148
If the provided type is nothrow move constructible, provides the member constant value equal to true....
Definition: is_nothrow_move_constructible.hpp:48