EtcPal  HEAD (unstable)
ETC Platform Abstraction Layer (EtcPal)
View other versions:
error.h
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright 2022 ETC Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *******************************************************************************
16  * This file is a part of EtcPal. For more information, go to:
17  * https://github.com/ETCLabs/EtcPal
18  ******************************************************************************/
19 
22 
23 #ifndef ETCPAL_CPP_ERROR_H_
24 #define ETCPAL_CPP_ERROR_H_
25 
26 #include <cassert>
27 #include <stdexcept>
28 #include <string>
29 #include "etcpal/error.h"
30 #include "etcpal/cpp/common.h"
31 
32 namespace etcpal
33 {
41 
43 // etcpal::Error
45 
93 class Error
94 {
95 public:
96  Error() = delete;
97  // Note: this constructor is not explicit by design, to allow implicit conversions e.g.
98  // etcpal::Error FunctionReturningError()
99  // {
100  // return kEtcPalErrOk;
101  // }
102  constexpr Error(etcpal_error_t code) noexcept;
103  Error& operator=(etcpal_error_t code) noexcept;
104 
105  constexpr bool IsOk() const noexcept;
106  constexpr etcpal_error_t code() const noexcept;
107  std::string ToString() const;
108  const char* ToCString() const noexcept;
109 
110  constexpr explicit operator bool() const noexcept;
111 
112  static constexpr Error Ok() noexcept;
113 
114 private:
116 };
117 
119 constexpr Error::Error(etcpal_error_t code) noexcept : code_(code)
120 {
121 }
122 
124 inline Error& Error::operator=(etcpal_error_t code) noexcept
125 {
126  code_ = code;
127  return *this;
128 }
129 
132 constexpr bool Error::IsOk() const noexcept
133 {
134  return code_ == kEtcPalErrOk;
135 }
136 
138 constexpr etcpal_error_t Error::code() const noexcept
139 {
140  return code_;
141 }
142 
144 inline std::string Error::ToString() const
145 {
146  return etcpal_strerror(code_);
147 }
148 
150 inline const char* Error::ToCString() const noexcept
151 {
152  return etcpal_strerror(code_);
153 }
154 
157 constexpr Error::operator bool() const noexcept
158 {
159  return IsOk();
160 }
161 
163 constexpr Error Error::Ok() noexcept
164 {
165  return {kEtcPalErrOk};
166 }
167 
170 
173 
174 constexpr bool operator==(etcpal_error_t code, const Error& error)
175 {
176  return code == error.code();
177 }
178 
179 constexpr bool operator!=(etcpal_error_t code, const Error& error)
180 {
181  return !(code == error);
182 }
183 
184 constexpr bool operator==(const Error& error, etcpal_error_t code)
185 {
186  return error.code() == code;
187 }
188 
189 constexpr bool operator!=(const Error& error, etcpal_error_t code)
190 {
191  return !(error == code);
192 }
193 
194 constexpr bool operator==(const Error& a, const Error& b)
195 {
196  return a.code() == b.code();
197 }
198 
199 constexpr bool operator!=(const Error& a, const Error& b)
200 {
201  return !(a == b);
202 }
203 
206 
208 // etcpal::BadExpectedAccess
210 
217 class BadExpectedAccess : public std::logic_error
218 {
219 public:
220  explicit BadExpectedAccess(Error err);
221  Error error() const noexcept;
222 
223 private:
224  Error err_;
225 };
226 
230  : std::logic_error("Bad access to etcpal::Expected::value(); the Expected instance contained error '" +
231  err.ToString() + "'.")
232  , err_(err)
233 {
234 }
235 
237 inline Error BadExpectedAccess::error() const noexcept
238 {
239  return err_;
240 }
241 
243 
245 // etcpal::Expected internals
247 
248 template <typename T>
249 class Expected;
250 
251 namespace detail
252 {
253 // This method of implementing Expected's storage, with copy and move functionality, was borrowed
254 // with love from a generic header-only expected implementation by martinmoene:
255 // https://github.com/martinmoene/expected-lite
256 // There are some NOLINT directives since this class does some tricky unexpected C++ stuff.
257 
258 template <typename T>
259 class ExpectedStorageImpl // NOLINT(cppcoreguidelines-special-member-functions)
260 {
261 public:
262  using ValueType = T;
263 
264  // Do not construct or destruct members on construction or destruction
265  ExpectedStorageImpl() {} // NOLINT(cppcoreguidelines-pro-type-member-init,modernize-use-equals-default)
266  ~ExpectedStorageImpl() {} // NOLINT(modernize-use-equals-default)
267 
268  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
269  explicit ExpectedStorageImpl(bool has_value) : has_value_(has_value) {}
270 
271  void ConstructValue(const ValueType& v) { new (&value_) ValueType(v); }
272  void ConstructValue(ValueType&& v) { new (&value_) ValueType(std::move(v)); }
273  void SetError(etcpal_error_t e) { error_ = e; }
274 
275  void DestructValue() { value_.~ValueType(); }
276 
277  constexpr const ValueType& value() const& { return value_; }
278  ValueType& value() & { return value_; }
279  constexpr const ValueType&& value() const&& { return std::move(value_); }
280  ETCPAL_CONSTEXPR_14 ValueType&& value() && { return std::move(value_); }
281  const ValueType* value_ptr() const { return &value_; }
282  ValueType* value_ptr() { return &value_; }
283 
284  etcpal_error_t error() const { return error_; }
285 
286  bool has_value() const { return has_value_; }
287  void SetHasValue(bool v) { has_value_ = v; }
288 
289 private:
290  bool has_value_{false};
291  union
292  {
293  ValueType value_; // NOLINT(readability-identifier-naming)
294  etcpal_error_t error_; // NOLINT(readability-identifier-naming)
295  };
296 };
297 
298 // The ExpectedStorage class provides a way to conditionally delete the copy and/or move
299 // constructors of etcpal::Expected based on the copyability and moveability of the T that we are
300 // being specialized with.
301 //
302 // We provide a generic template where the copy and move constructors are both deleted, then 3
303 // specializations, for (copyable and movable), (copyable and not moveable), and (moveable and not
304 // copyable) respectively.
305 template <typename T, bool IsCopyConstructible, bool IsMoveConstructible>
306 // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
307 class ExpectedStorage : public ExpectedStorageImpl<T>
308 {
309 public:
310  ExpectedStorage() = default;
311  ~ExpectedStorage() = default;
312 
313  explicit ExpectedStorage(bool has_value) : ExpectedStorageImpl<T>(has_value) {}
314 
315  ExpectedStorage(const ExpectedStorage& other) = delete;
316  ExpectedStorage(ExpectedStorage&& other) = delete;
317 };
318 
319 template <typename T>
320 // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
321 class ExpectedStorage<T, true, true> : public ExpectedStorageImpl<T>
322 {
323 public:
324  ExpectedStorage() = default;
325  ~ExpectedStorage() = default;
326 
327  explicit ExpectedStorage(bool has_value) : ExpectedStorageImpl<T>(has_value) {}
328 
329  ExpectedStorage(const ExpectedStorage& other) : ExpectedStorageImpl<T>(other.has_value())
330  {
331  if (this->has_value())
332  this->ConstructValue(other.value());
333  else
334  this->SetError(other.error());
335  }
336 
337  ExpectedStorage(ExpectedStorage&& other) : ExpectedStorageImpl<T>(other.has_value())
338  {
339  if (this->has_value())
340  this->ConstructValue(std::move(other.value()));
341  else
342  this->SetError(other.error());
343  }
344 };
345 
346 template <typename T>
347 // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
348 class ExpectedStorage<T, true, false> : public ExpectedStorageImpl<T>
349 {
350 public:
351  ExpectedStorage() = default;
352  ~ExpectedStorage() = default;
353 
354  explicit ExpectedStorage(bool has_value) : ExpectedStorageImpl<T>(has_value) {}
355 
356  ExpectedStorage(const ExpectedStorage& other) : ExpectedStorageImpl<T>(other.has_value())
357  {
358  if (this->has_value())
359  this->ConstructValue(other.value());
360  else
361  this->SetError(other.error());
362  }
363 
364  ExpectedStorage(ExpectedStorage&& other) = delete;
365 };
366 
367 template <typename T>
368 // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
369 class ExpectedStorage<T, false, true> : public ExpectedStorageImpl<T>
370 {
371 public:
372  ExpectedStorage() = default;
373  ~ExpectedStorage() = default;
374 
375  explicit ExpectedStorage(bool has_value) : ExpectedStorageImpl<T>(has_value) {}
376 
377  ExpectedStorage(ExpectedStorage const& other) = delete;
378 
379  ExpectedStorage(ExpectedStorage&& other) : ExpectedStorageImpl<T>(other.has_value())
380  {
381  if (this->has_value())
382  this->ConstructValue(std::move(other.value()));
383  else
384  this->SetError(other.error());
385  }
386 };
387 }; // namespace detail
388 
390 
392 // etcpal::Expected
394 
475 template <typename T>
476 class Expected // NOLINT(cppcoreguidelines-special-member-functions)
477 {
478 private:
479  template <typename>
480  friend class Expected;
481 
482 public:
483  static_assert(!std::is_reference<T>::value, "T must not be a reference");
484  static_assert(!std::is_same<T, etcpal_error_t>::value, "T must not be etcpal_error_t");
485  static_assert(!std::is_same<T, Error>::value, "T must not be etcpal::Error");
486  static_assert(!std::is_void<T>::value, "T must not be void");
487 
489  using ValueType = T;
490 
491  // Typical ETC library style is to place all function definitions outside the class definition;
492  // however, this gets nasty with these templates so the constructors are an exception here.
493 
494  // clang-format off
495 
500  template <bool B = std::is_default_constructible<T>::value, typename std::enable_if<B, int>::type = 0>
501  ETCPAL_CONSTEXPR_14 Expected() : contained_(true)
502  {
503  contained_.ConstructValue(ValueType());
504  }
505 
510  ETCPAL_CONSTEXPR_14 Expected(const Expected& other) = default;
511 
517 
522  template<typename U>
523  ETCPAL_CONSTEXPR_14 explicit Expected(const Expected<U>& other,
524  ETCPAL_ENABLE_IF_ARG(
525  std::is_constructible<T, const U&>::value &&
526  !std::is_constructible<T, Expected<U>&>::value &&
527  !std::is_constructible<T, Expected<U> && >::value &&
528  !std::is_constructible<T, Expected<U> const & >::value &&
529  !std::is_constructible<T, Expected<U> const && >::value &&
530  !std::is_convertible< Expected<U> & , T>::value &&
531  !std::is_convertible< Expected<U> &&, T>::value &&
532  !std::is_convertible< Expected<U> const & , T>::value &&
533  !std::is_convertible< Expected<U> const &&, T>::value &&
534  !std::is_convertible<const U&, T>::value
535  ))
536  : contained_(other.has_value())
537  {
538  if (has_value())
539  contained_.ConstructValue(T{other.contained_.value()});
540  else
541  contained_.SetError(other.contained_.error());
542  }
543 
548  template<typename U>
550  ETCPAL_ENABLE_IF_ARG(
551  std::is_constructible<T, const U&>::value &&
552  !std::is_constructible<T, Expected<U> & >::value &&
553  !std::is_constructible<T, Expected<U> && >::value &&
554  !std::is_constructible<T, Expected<U> const & >::value &&
555  !std::is_constructible<T, Expected<U> const && >::value &&
556  !std::is_convertible< Expected<U> & , T>::value &&
557  !std::is_convertible< Expected<U> &&, T>::value &&
558  !std::is_convertible< Expected<U> const &, T>::value &&
559  !std::is_convertible< Expected<U> const &&, T>::value &&
560  std::is_convertible<const U&, T>::value
561  ))
562  : contained_(other.has_value())
563  {
564  if (has_value())
565  contained_.ConstructValue(other.contained_.value());
566  else
567  contained_.SetError(other.contained_.error());
568  }
569 
574  template<typename U>
576  ETCPAL_ENABLE_IF_ARG(
577  std::is_constructible<T, U>::value &&
578  !std::is_constructible<T, Expected<U> & >::value &&
579  !std::is_constructible<T, Expected<U> && >::value &&
580  !std::is_constructible<T, Expected<U> const & >::value &&
581  !std::is_constructible<T, Expected<U> const && >::value &&
582  !std::is_convertible< Expected<U> & , T>::value &&
583  !std::is_convertible< Expected<U> &&, T>::value &&
584  !std::is_convertible< Expected<U> const & , T>::value &&
585  !std::is_convertible< Expected<U> const &&, T>::value &&
586  !std::is_convertible<U, T>::value
587  ))
588  : contained_(other.has_value())
589  {
590  if (has_value())
591  contained_.ConstructValue(T{std::move(other.contained_.value())});
592  else
593  contained_.SetError(other.contained_.error());
594  }
595 
600  template<typename U>
602  ETCPAL_ENABLE_IF_ARG(
603  std::is_constructible<T, U>::value &&
604  !std::is_constructible<T, Expected<U> & >::value &&
605  !std::is_constructible<T, Expected<U> && >::value &&
606  !std::is_constructible<T, Expected<U> const & >::value &&
607  !std::is_constructible<T, Expected<U> const && >::value &&
608  !std::is_convertible< Expected<U> & , T>::value &&
609  !std::is_convertible< Expected<U> &&, T>::value &&
610  !std::is_convertible< Expected<U> const & , T>::value &&
611  !std::is_convertible< Expected<U> const &&, T>::value &&
612  std::is_convertible<U, T>::value
613  ))
614  : contained_(other.has_value())
615  {
616  if (has_value())
617  contained_.ConstructValue(std::move(other.contained_.value()));
618  else
619  contained_.SetError(other.contained_.error());
620  }
621 
629  template <typename U = T>
631  ETCPAL_ENABLE_IF_ARG( std::is_constructible<T, U&&>::value &&
632  !std::is_convertible<U&&, T>::value
633  )) noexcept(std::is_nothrow_move_constructible<U>::value)
634  : contained_(true)
635  {
636  contained_.ConstructValue(T{std::forward<U>(value)});
637  }
638 
646  template <typename U = T>
647  ETCPAL_CONSTEXPR_14 Expected(U&& value, ETCPAL_ENABLE_IF_ARG(std::is_constructible<T, U&&>::value &&
648  std::is_convertible<U&&, T>::value
649  )) noexcept(std::is_nothrow_move_constructible<U>::value)
650  : contained_(true)
651  {
652  contained_.ConstructValue(std::forward<U>(value));
653  }
654 
655  // clang-format on
656 
657  // Always implicit by design
659  ~Expected();
660 
661  constexpr const T* operator->() const;
662  T* operator->();
663  constexpr const T& operator*() const&;
664  T& operator*() &;
665  constexpr const T&& operator*() const&&;
666  ETCPAL_CONSTEXPR_14 T&& operator*() &&;
667  constexpr explicit operator bool() const noexcept;
668  constexpr bool has_value() const noexcept;
669  ETCPAL_CONSTEXPR_14 const T& value() const&;
670  T& value() &;
671  ETCPAL_CONSTEXPR_14 const T&& value() const&&;
672  ETCPAL_CONSTEXPR_14 T&& value() &&;
673  constexpr etcpal_error_t error_code() const noexcept;
674  constexpr Error error() const noexcept;
675 
676  // clang-format off
677 
680  template <typename U,
681  ETCPAL_ENABLE_IF_TEMPLATE(std::is_copy_constructible<T>::value && std::is_convertible<U&&, T>::value)>
682  constexpr T value_or(U&& def_val) const&
683  {
684  return has_value() ? contained_.value() : static_cast<T>(std::forward<U>(def_val));
685  }
686 
689  template <typename U,
690  ETCPAL_ENABLE_IF_TEMPLATE(std::is_move_constructible<T>::value && std::is_convertible<U&&, T>::value)>
691  T value_or(U&& def_val) &&
692  {
693  return has_value() ? contained_.value() : static_cast<T>(std::forward<U>(def_val));
694  }
695 
696  // clang-format on
697 
698 private:
699  detail::ExpectedStorage<T, std::is_copy_constructible<T>::value, std::is_move_constructible<T>::value> contained_;
700 }; // namespace etcpal
701 
703 template <typename T>
705 {
706  contained_.SetError(error);
707 }
708 
710 template <typename T>
712 {
713  if (has_value())
714  contained_.DestructValue();
715 }
716 
720 template <typename T>
721 constexpr const T* Expected<T>::operator->() const
722 {
723  // Comma syntax is to satisfy C++11 requirements for constexpr
724  return assert(has_value()), contained_.value_ptr();
725 }
726 
730 template <typename T>
732 {
733  // Comma syntax is to satisfy C++11 requirements for constexpr
734  return assert(has_value()), contained_.value_ptr();
735 }
736 
740 template <typename T>
741 constexpr const T& Expected<T>::operator*() const&
742 {
743  // Comma syntax is to satisfy C++11 requirements for constexpr
744  return assert(has_value()), contained_.value();
745 }
746 
750 template <typename T>
752 {
753  // Comma syntax is to satisfy C++11 requirements for constexpr
754  return assert(has_value()), contained_.value();
755 }
756 
760 template <typename T>
761 constexpr const T&& Expected<T>::operator*() const&&
762 {
763  // Comma syntax is to satisfy C++11 requirements for constexpr
764  return assert(has_value()), std::move(contained_.value());
765 }
766 
770 template <typename T>
772 {
773  // Comma syntax is to satisfy C++11 requirements for constexpr
774  return assert(has_value()), std::move(contained_.value());
775 }
776 
778 template <typename T>
779 constexpr Expected<T>::operator bool() const noexcept
780 {
781  return has_value();
782 }
783 
785 template <typename T>
786 constexpr bool Expected<T>::has_value() const noexcept
787 {
788  return contained_.has_value();
789 }
790 
793 template <typename T>
795 {
796  if (!has_value())
797  ETCPAL_THROW(BadExpectedAccess(contained_.error()));
798  return contained_.value();
799 }
800 
803 template <typename T>
805 {
806  if (!has_value())
807  ETCPAL_THROW(BadExpectedAccess(contained_.error()));
808  return contained_.value();
809 }
810 
813 template <typename T>
815 {
816  if (!has_value())
817  ETCPAL_THROW(BadExpectedAccess(contained_.error()));
818  return std::move(contained_.value());
819 }
820 
823 template <typename T>
825 {
826  if (!has_value())
827  ETCPAL_THROW(BadExpectedAccess(contained_.error()));
828  return std::move(contained_.value());
829 }
830 
834 template <typename T>
835 constexpr etcpal_error_t Expected<T>::error_code() const noexcept
836 {
837  // Comma syntax is to satisfy C++11 requirements for constexpr
838  return assert(!has_value()), contained_.error();
839 }
840 
844 template <typename T>
845 constexpr Error Expected<T>::error() const noexcept
846 {
847  // Comma syntax is to satisfy C++11 requirements for constexpr
848  return assert(!has_value()), contained_.error();
849 }
850 
853 
856 
857 template <typename T1, typename T2>
858 constexpr bool operator==(const Expected<T1>& x, const Expected<T2>& y)
859 {
860  return bool(x) != bool(y) ? false : !bool(x) ? x.error_code() == y.error_code() : *x == *y;
861 }
862 
863 template <typename T1, typename T2>
864 constexpr bool operator!=(const Expected<T1>& x, const Expected<T2>& y)
865 {
866  return !(x == y);
867 }
868 
869 template <typename T1, typename T2>
870 constexpr bool operator==(const Expected<T1>& x, const T2& v)
871 {
872  return bool(x) ? *x == v : false;
873 }
874 
875 template <typename T1, typename T2>
876 constexpr bool operator==(const T2& v, const Expected<T1>& x)
877 {
878  return bool(x) ? v == *x : false;
879 }
880 
881 template <typename T1, typename T2>
882 constexpr bool operator!=(const Expected<T1>& x, const T2& v)
883 {
884  return bool(x) ? *x != v : true;
885 }
886 
887 template <typename T1, typename T2>
888 constexpr bool operator!=(const T2& v, const Expected<T1>& x)
889 {
890  return bool(x) ? v != *x : true;
891 }
892 
893 template <typename T>
894 constexpr bool operator==(const Expected<T>& x, etcpal_error_t e)
895 {
896  return (!x) ? x.error_code() == e : false;
897 }
898 
899 template <typename T>
900 constexpr bool operator==(etcpal_error_t e, const Expected<T>& x)
901 {
902  return (x == e);
903 }
904 
905 template <typename T>
906 constexpr bool operator!=(const Expected<T>& x, etcpal_error_t e)
907 {
908  return !(x == e);
909 }
910 
911 template <typename T>
912 constexpr bool operator!=(etcpal_error_t e, const Expected<T>& x)
913 {
914  return !(x == e);
915 }
916 
919 
920 }; // namespace etcpal
921 
922 #endif // ETCPAL_CPP_ERROR_H_
Exception representing bad access to an Expected instance.
Definition: error.h:218
BadExpectedAccess(Error err)
Construct from a Error.
Definition: error.h:229
Error error() const noexcept
Get the error code which was contained in the associated Expected when the exception occurred.
Definition: error.h:237
A wrapper class for the EtcPal error type.
Definition: error.h:94
constexpr bool IsOk() const noexcept
Whether this Error contains the code kEtcPalErrOk.
Definition: error.h:132
std::string ToString() const
Get a descriptive string for this Error as a std::string.
Definition: error.h:144
Error & operator=(etcpal_error_t code) noexcept
Assign an error code to this Error.
Definition: error.h:124
constexpr etcpal_error_t code() const noexcept
Get the underlying code from a Error.
Definition: error.h:138
const char * ToCString() const noexcept
Get a descriptive string for this Error as a C string.
Definition: error.h:150
static constexpr Error Ok() noexcept
Construct an Error containing kEtcPalErrOk.
Definition: error.h:163
A type representing either a value or an etcpal_error_t code.
Definition: error.h:477
ETCPAL_CONSTEXPR_14 Expected(Expected< U > &&other, ETCPAL_ENABLE_IF_ARG(std::is_constructible< T, U >::value &&!std::is_constructible< T, Expected< U > & >::value &&!std::is_constructible< T, Expected< U > && >::value &&!std::is_constructible< T, Expected< U > const & >::value &&!std::is_constructible< T, Expected< U > const && >::value &&!std::is_convertible< Expected< U > &, T >::value &&!std::is_convertible< Expected< U > &&, T >::value &&!std::is_convertible< Expected< U > const &, T >::value &&!std::is_convertible< Expected< U > const &&, T >::value &&!std::is_convertible< U, T >::value))
Explicit conversion move constructor - enabled for U that can be explicitly converted to T.
Definition: error.h:575
ETCPAL_CONSTEXPR_14 const T & value() const &
Get the underlying value.
Definition: error.h:794
ETCPAL_CONSTEXPR_14 Expected(U &&value, ETCPAL_ENABLE_IF_ARG(std::is_constructible< T, U && >::value &&!std::is_convertible< U &&, T >::value)) noexcept(std::is_nothrow_move_constructible< U >::value)
Construct from value, explicit.
Definition: error.h:630
constexpr const T * operator->() const
Access members of a composite contained value.
Definition: error.h:721
ETCPAL_CONSTEXPR_14 Expected(const Expected< U > &other, ETCPAL_ENABLE_IF_ARG(std::is_constructible< T, const U & >::value &&!std::is_constructible< T, Expected< U > & >::value &&!std::is_constructible< T, Expected< U > && >::value &&!std::is_constructible< T, Expected< U > const & >::value &&!std::is_constructible< T, Expected< U > const && >::value &&!std::is_convertible< Expected< U > &, T >::value &&!std::is_convertible< Expected< U > &&, T >::value &&!std::is_convertible< Expected< U > const &, T >::value &&!std::is_convertible< Expected< U > const &&, T >::value &&std::is_convertible< const U &, T >::value))
Implicit conversion copy constructor - enabled for U that can be implicitly converted to T.
Definition: error.h:549
constexpr Error error() const noexcept
Get the error code as a Error object.
Definition: error.h:845
constexpr const T & operator*() const &
Get the underlying value.
Definition: error.h:741
constexpr bool has_value() const noexcept
Whether this Expected instance contains a valid value. If not, contains an error code.
Definition: error.h:786
constexpr T value_or(U &&def_val) const &
Get the value, or a default value if this Expected contains an error.
Definition: error.h:682
~Expected()
Calls the contained value's destructor if and only if has_value() is true.
Definition: error.h:711
ETCPAL_CONSTEXPR_14 Expected()
Default constructor - enabled if T is default-constructible.
Definition: error.h:501
ETCPAL_CONSTEXPR_14 Expected(const Expected< U > &other, ETCPAL_ENABLE_IF_ARG(std::is_constructible< T, const U & >::value &&!std::is_constructible< T, Expected< U > & >::value &&!std::is_constructible< T, Expected< U > && >::value &&!std::is_constructible< T, Expected< U > const & >::value &&!std::is_constructible< T, Expected< U > const && >::value &&!std::is_convertible< Expected< U > &, T >::value &&!std::is_convertible< Expected< U > &&, T >::value &&!std::is_convertible< Expected< U > const &, T >::value &&!std::is_convertible< Expected< U > const &&, T >::value &&!std::is_convertible< const U &, T >::value))
Explicit conversion copy constructor - enabled for U that can be explicitly converted to T.
Definition: error.h:523
ETCPAL_CONSTEXPR_14 Expected(Expected< U > &&other, ETCPAL_ENABLE_IF_ARG(std::is_constructible< T, U >::value &&!std::is_constructible< T, Expected< U > & >::value &&!std::is_constructible< T, Expected< U > && >::value &&!std::is_constructible< T, Expected< U > const & >::value &&!std::is_constructible< T, Expected< U > const && >::value &&!std::is_convertible< Expected< U > &, T >::value &&!std::is_convertible< Expected< U > &&, T >::value &&!std::is_convertible< Expected< U > const &, T >::value &&!std::is_convertible< Expected< U > const &&, T >::value &&std::is_convertible< U, T >::value))
Implicit conversion move constructor - enabled for U that can be implicitly converted to T.
Definition: error.h:601
ETCPAL_CONSTEXPR_14 Expected(U &&value, ETCPAL_ENABLE_IF_ARG(std::is_constructible< T, U && >::value &&std::is_convertible< U &&, T >::value)) noexcept(std::is_nothrow_move_constructible< U >::value)
Construct from value, implicit.
Definition: error.h:647
T value_or(U &&def_val) &&
Get the value, or a default value if this Expected contains an error.
Definition: error.h:691
ETCPAL_CONSTEXPR_14 Expected(Expected &&other)=default
Move constructor - enabled if T is move-constructible.
constexpr etcpal_error_t error_code() const noexcept
Get the error code.
Definition: error.h:835
T ValueType
The value type.
Definition: error.h:489
ETCPAL_CONSTEXPR_14 Expected(const Expected &other)=default
Copy constructor - enabled if T is copy-constructible.
Common definitions used by EtcPal C++ wrappers.
#define ETCPAL_CONSTEXPR_14
Stand-in for "constexpr" on entities that can only be defined "constexpr" in C++14 or later.
Definition: common.h:53
const char * etcpal_strerror(etcpal_error_t code)
Get a string representation of an error code.
Definition: error.c:69
etcpal_error_t
A set of error codes that can be returned by library functions.
Definition: error.h:49
@ kEtcPalErrOk
The call was successful, no error occurred.
Definition: error.h:51