23 #ifndef ETCPAL_CPP_ERROR_H_
24 #define ETCPAL_CPP_ERROR_H_
29 #include "etcpal/error.h"
105 constexpr
bool IsOk()
const noexcept;
110 constexpr
explicit operator bool()
const noexcept;
112 static constexpr
Error Ok() noexcept;
157 constexpr Error::operator bool() const noexcept
176 return code == error.
code();
179 constexpr
bool operator!=(
etcpal_error_t code,
const Error& error)
181 return !(code == error);
184 constexpr
bool operator==(
const Error& error,
etcpal_error_t code)
186 return error.code() == code;
189 constexpr
bool operator!=(
const Error& error,
etcpal_error_t code)
191 return !(error == code);
194 constexpr
bool operator==(
const Error& a,
const Error& b)
196 return a.code() == b.code();
199 constexpr
bool operator!=(
const Error& a,
const Error& b)
230 : std::logic_error(
"Bad access to etcpal::Expected::value(); the Expected instance contained error '" +
231 err.ToString() +
"'.")
248 template <
typename T>
258 template <
typename T>
259 class ExpectedStorageImpl
265 ExpectedStorageImpl() {}
266 ~ExpectedStorageImpl() {}
269 explicit ExpectedStorageImpl(
bool has_value) : has_value_(has_value) {}
271 void ConstructValue(
const ValueType& v) {
new (&value_) ValueType(v); }
272 void ConstructValue(ValueType&& v) {
new (&value_) ValueType(std::move(v)); }
275 void DestructValue() { value_.~ValueType(); }
277 constexpr
const ValueType& value() const& {
return value_; }
278 ValueType& value() & {
return value_; }
279 constexpr
const ValueType&& value() const&& {
return std::move(value_); }
281 const ValueType* value_ptr()
const {
return &value_; }
282 ValueType* value_ptr() {
return &value_; }
286 bool has_value()
const {
return has_value_; }
287 void SetHasValue(
bool v) { has_value_ = v; }
290 bool has_value_{
false};
305 template <
typename T,
bool IsCopyConstructible,
bool IsMoveConstructible>
307 class ExpectedStorage :
public ExpectedStorageImpl<T>
310 ExpectedStorage() =
default;
311 ~ExpectedStorage() =
default;
313 explicit ExpectedStorage(
bool has_value) : ExpectedStorageImpl<T>(has_value) {}
315 ExpectedStorage(
const ExpectedStorage& other) =
delete;
316 ExpectedStorage(ExpectedStorage&& other) =
delete;
319 template <
typename T>
321 class ExpectedStorage<T, true, true> :
public ExpectedStorageImpl<T>
324 ExpectedStorage() =
default;
325 ~ExpectedStorage() =
default;
327 explicit ExpectedStorage(
bool has_value) : ExpectedStorageImpl<T>(has_value) {}
329 ExpectedStorage(
const ExpectedStorage& other) : ExpectedStorageImpl<T>(other.has_value())
331 if (this->has_value())
332 this->ConstructValue(other.value());
334 this->SetError(other.error());
337 ExpectedStorage(ExpectedStorage&& other) : ExpectedStorageImpl<T>(other.has_value())
339 if (this->has_value())
340 this->ConstructValue(std::move(other.value()));
342 this->SetError(other.error());
346 template <
typename T>
348 class ExpectedStorage<T, true, false> :
public ExpectedStorageImpl<T>
351 ExpectedStorage() =
default;
352 ~ExpectedStorage() =
default;
354 explicit ExpectedStorage(
bool has_value) : ExpectedStorageImpl<T>(has_value) {}
356 ExpectedStorage(
const ExpectedStorage& other) : ExpectedStorageImpl<T>(other.has_value())
358 if (this->has_value())
359 this->ConstructValue(other.value());
361 this->SetError(other.error());
364 ExpectedStorage(ExpectedStorage&& other) =
delete;
367 template <
typename T>
369 class ExpectedStorage<T, false, true> :
public ExpectedStorageImpl<T>
372 ExpectedStorage() =
default;
373 ~ExpectedStorage() =
default;
375 explicit ExpectedStorage(
bool has_value) : ExpectedStorageImpl<T>(has_value) {}
377 ExpectedStorage(ExpectedStorage
const& other) =
delete;
379 ExpectedStorage(ExpectedStorage&& other) : ExpectedStorageImpl<T>(other.has_value())
381 if (this->has_value())
382 this->ConstructValue(std::move(other.value()));
384 this->SetError(other.error());
475 template <
typename T>
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");
500 template <bool B = std::is_default_constructible<T>::value,
typename std::enable_if<B, int>::type = 0>
524 ETCPAL_ENABLE_IF_ARG(
525 std::is_constructible<T, const U&>::value &&
534 !std::is_convertible<const U&, T>::value
539 contained_.ConstructValue(T{other.contained_.value()});
541 contained_.SetError(other.contained_.error());
550 ETCPAL_ENABLE_IF_ARG(
551 std::is_constructible<T, const U&>::value &&
560 std::is_convertible<const U&, T>::value
565 contained_.ConstructValue(other.contained_.value());
567 contained_.SetError(other.contained_.error());
576 ETCPAL_ENABLE_IF_ARG(
577 std::is_constructible<T, U>::value &&
586 !std::is_convertible<U, T>::value
591 contained_.ConstructValue(T{std::move(other.contained_.value())});
593 contained_.SetError(other.contained_.error());
602 ETCPAL_ENABLE_IF_ARG(
603 std::is_constructible<T, U>::value &&
612 std::is_convertible<U, T>::value
617 contained_.ConstructValue(std::move(other.contained_.value()));
619 contained_.SetError(other.contained_.error());
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)
636 contained_.ConstructValue(T{std::forward<U>(
value)});
646 template <
typename U = T>
648 std::is_convertible<U&&, T>::value
649 )) noexcept(std::is_nothrow_move_constructible<U>::value)
652 contained_.ConstructValue(std::forward<U>(
value));
665 constexpr const T&& operator*() const&&;
667 constexpr explicit operator
bool() const noexcept;
668 constexpr
bool has_value() const noexcept;
680 template <typename U,
681 ETCPAL_ENABLE_IF_TEMPLATE(std::is_copy_constructible<T>::
value && std::is_convertible<U&&, T>::
value)>
684 return has_value() ? contained_.value() :
static_cast<T
>(std::forward<U>(def_val));
689 template <
typename U,
690 ETCPAL_ENABLE_IF_TEMPLATE(std::is_move_constructible<T>::value && std::is_convertible<U&&, T>::value)>
693 return has_value() ? contained_.value() :
static_cast<T
>(std::forward<U>(def_val));
699 detail::ExpectedStorage<T, std::is_copy_constructible<T>::value, std::is_move_constructible<T>::value> contained_;
703 template <
typename T>
706 contained_.SetError(
error);
710 template <
typename T>
714 contained_.DestructValue();
720 template <
typename T>
724 return assert(has_value()), contained_.value_ptr();
730 template <
typename T>
734 return assert(has_value()), contained_.value_ptr();
740 template <
typename T>
744 return assert(has_value()), contained_.value();
750 template <
typename T>
754 return assert(has_value()), contained_.value();
760 template <
typename T>
764 return assert(has_value()), std::move(contained_.value());
770 template <
typename T>
774 return assert(has_value()), std::move(contained_.value());
778 template <
typename T>
785 template <
typename T>
788 return contained_.has_value();
793 template <
typename T>
798 return contained_.value();
803 template <
typename T>
808 return contained_.value();
813 template <
typename T>
818 return std::move(contained_.value());
823 template <
typename T>
828 return std::move(contained_.value());
834 template <
typename T>
838 return assert(!has_value()), contained_.error();
844 template <
typename T>
848 return assert(!has_value()), contained_.error();
857 template <
typename T1,
typename T2>
863 template <
typename T1,
typename T2>
864 constexpr
bool operator!=(
const Expected<T1>& x,
const Expected<T2>& y)
869 template <
typename T1,
typename T2>
870 constexpr
bool operator==(
const Expected<T1>& x,
const T2& v)
872 return bool(x) ? *x == v :
false;
875 template <
typename T1,
typename T2>
876 constexpr
bool operator==(
const T2& v,
const Expected<T1>& x)
878 return bool(x) ? v == *x :
false;
881 template <
typename T1,
typename T2>
882 constexpr
bool operator!=(
const Expected<T1>& x,
const T2& v)
884 return bool(x) ? *x != v :
true;
887 template <
typename T1,
typename T2>
888 constexpr
bool operator!=(
const T2& v,
const Expected<T1>& x)
890 return bool(x) ? v != *x :
true;
893 template <
typename T>
896 return (!x) ? x.error_code() == e :
false;
899 template <
typename T>
905 template <
typename T>
911 template <
typename T>
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