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>
257 template <
typename T>
258 class ExpectedStorageImpl
264 ExpectedStorageImpl() {}
265 ~ExpectedStorageImpl() {}
266 explicit ExpectedStorageImpl(
bool has_value) : has_value_(has_value) {}
268 void ConstructValue(
const ValueType& v) {
new (&value_) ValueType(v); }
269 void ConstructValue(ValueType&& v) {
new (&value_) ValueType(std::move(v)); }
272 void DestructValue() { value_.~ValueType(); }
274 constexpr
const ValueType& value() const& {
return value_; }
275 ValueType& value() & {
return value_; }
276 constexpr
const ValueType&& value() const&& {
return std::move(value_); }
278 const ValueType* value_ptr()
const {
return &value_; }
279 ValueType* value_ptr() {
return &value_; }
283 bool has_value()
const {
return has_value_; }
284 void SetHasValue(
bool v) { has_value_ = v; }
287 bool has_value_{
false};
302 template <
typename T,
bool IsCopyConstructible,
bool IsMoveConstructible>
303 class ExpectedStorage :
public ExpectedStorageImpl<T>
306 ExpectedStorage() =
default;
307 ~ExpectedStorage() =
default;
309 explicit ExpectedStorage(
bool has_value) : ExpectedStorageImpl<T>(has_value) {}
311 ExpectedStorage(
const ExpectedStorage& other) =
delete;
312 ExpectedStorage(ExpectedStorage&& other) =
delete;
315 template <
typename T>
316 class ExpectedStorage<T, true, true> :
public ExpectedStorageImpl<T>
319 ExpectedStorage() =
default;
320 ~ExpectedStorage() =
default;
322 explicit ExpectedStorage(
bool has_value) : ExpectedStorageImpl<T>(has_value) {}
324 ExpectedStorage(
const ExpectedStorage& other) : ExpectedStorageImpl<T>(other.has_value())
326 if (this->has_value())
327 this->ConstructValue(other.value());
329 this->SetError(other.error());
332 ExpectedStorage(ExpectedStorage&& other) : ExpectedStorageImpl<T>(other.has_value())
334 if (this->has_value())
335 this->ConstructValue(std::move(other.value()));
337 this->SetError(other.error());
341 template <
typename T>
342 class ExpectedStorage<T, true, false> :
public ExpectedStorageImpl<T>
345 ExpectedStorage() =
default;
346 ~ExpectedStorage() =
default;
348 explicit ExpectedStorage(
bool has_value) : ExpectedStorageImpl<T>(has_value) {}
350 ExpectedStorage(
const ExpectedStorage& other) : ExpectedStorageImpl<T>(other.has_value())
352 if (this->has_value())
353 this->ConstructValue(other.value());
355 this->SetError(other.error());
358 ExpectedStorage(ExpectedStorage&& other) =
delete;
361 template <
typename T>
362 class ExpectedStorage<T, false, true> :
public ExpectedStorageImpl<T>
365 ExpectedStorage() =
default;
366 ~ExpectedStorage() =
default;
368 explicit ExpectedStorage(
bool has_value) : ExpectedStorageImpl<T>(has_value) {}
370 ExpectedStorage(ExpectedStorage
const& other) =
delete;
372 ExpectedStorage(ExpectedStorage&& other) : ExpectedStorageImpl<T>(other.has_value())
374 if (this->has_value())
375 this->ConstructValue(std::move(other.value()));
377 this->SetError(other.error());
468 template <
typename T>
476 static_assert(!std::is_reference<T>::value,
"T must not be a reference");
477 static_assert(!std::is_same<T, etcpal_error_t>::value,
"T must not be etcpal_error_t");
478 static_assert(!std::is_same<T, Error>::value,
"T must not be etcpal::Error");
479 static_assert(!std::is_void<T>::value,
"T must not be void");
493 template <bool B = std::is_default_constructible<T>::value,
typename std::enable_if<B, int>::type = 0>
517 ETCPAL_ENABLE_IF_ARG(
518 std::is_constructible<T, const U&>::value &&
527 !std::is_convertible<const U&, T>::value
532 contained_.ConstructValue(T{other.contained_.value()});
534 contained_.SetError(other.contained_.error());
543 ETCPAL_ENABLE_IF_ARG(
544 std::is_constructible<T, const U&>::value &&
553 std::is_convertible<const U&, T>::value
558 contained_.ConstructValue(other.contained_.value());
560 contained_.SetError(other.contained_.error());
569 ETCPAL_ENABLE_IF_ARG(
570 std::is_constructible<T, U>::value &&
579 !std::is_convertible<U, T>::value
584 contained_.ConstructValue(T{std::move(other.contained_.value())});
586 contained_.SetError(other.contained_.error());
595 ETCPAL_ENABLE_IF_ARG(
596 std::is_constructible<T, U>::value &&
605 std::is_convertible<U, T>::value
610 contained_.ConstructValue(std::move(other.contained_.value()));
612 contained_.SetError(other.contained_.error());
622 template <
typename U = T>
624 ETCPAL_ENABLE_IF_ARG( std::is_constructible<T, U&&>::value &&
625 !std::is_convertible<U&&, T>::value
626 )) noexcept(std::is_nothrow_move_constructible<U>::value)
629 contained_.ConstructValue(T{std::forward<U>(
value)});
639 template <
typename U = T>
641 std::is_convertible<U&&, T>::value
642 )) noexcept(std::is_nothrow_move_constructible<U>::value)
645 contained_.ConstructValue(std::forward<U>(
value));
658 constexpr const T&& operator*() const&&;
660 constexpr explicit operator
bool() const noexcept;
661 constexpr
bool has_value() const noexcept;
673 template <typename U,
674 ETCPAL_ENABLE_IF_TEMPLATE(std::is_copy_constructible<T>::
value && std::is_convertible<U&&, T>::
value)>
677 return has_value() ? contained_.value() :
static_cast<T
>(std::forward<U>(def_val));
682 template <
typename U,
683 ETCPAL_ENABLE_IF_TEMPLATE(std::is_move_constructible<T>::value && std::is_convertible<U&&, T>::value)>
686 return has_value() ? contained_.value() :
static_cast<T
>(std::forward<U>(def_val));
692 detail::ExpectedStorage<T, std::is_copy_constructible<T>::value, std::is_move_constructible<T>::value> contained_;
696 template <
typename T>
699 contained_.SetError(
error);
703 template <
typename T>
707 contained_.DestructValue();
713 template <
typename T>
717 return assert(has_value()), contained_.value_ptr();
723 template <
typename T>
727 return assert(has_value()), contained_.value_ptr();
733 template <
typename T>
737 return assert(has_value()), contained_.value();
743 template <
typename T>
747 return assert(has_value()), contained_.value();
753 template <
typename T>
757 return assert(has_value()), std::move(contained_.value());
763 template <
typename T>
767 return assert(has_value()), std::move(contained_.value());
771 template <
typename T>
778 template <
typename T>
781 return contained_.has_value();
786 template <
typename T>
791 return contained_.value();
796 template <
typename T>
801 return contained_.value();
806 template <
typename T>
811 return std::move(contained_.value());
816 template <
typename T>
821 return std::move(contained_.value());
827 template <
typename T>
831 return assert(!has_value()), contained_.error();
837 template <
typename T>
841 return assert(!has_value()), contained_.error();
850 template <
typename T1,
typename T2>
853 return bool(x) != bool(y) ? false : bool(x) ==
false ? x.
error_code() == y.
error_code() : *x == *y;
856 template <
typename T1,
typename T2>
857 constexpr
bool operator!=(
const Expected<T1>& x,
const Expected<T2>& y)
862 template <
typename T1,
typename T2>
863 constexpr
bool operator==(
const Expected<T1>& x,
const T2& v)
865 return bool(x) ? *x == v :
false;
868 template <
typename T1,
typename T2>
869 constexpr
bool operator==(
const T2& v,
const Expected<T1>& x)
871 return bool(x) ? v == *x :
false;
874 template <
typename T1,
typename T2>
875 constexpr
bool operator!=(
const Expected<T1>& x,
const T2& v)
877 return bool(x) ? *x != v :
true;
880 template <
typename T1,
typename T2>
881 constexpr
bool operator!=(
const T2& v,
const Expected<T1>& x)
883 return bool(x) ? v != *x :
true;
886 template <
typename T>
889 return (!x) ? x.error_code() == e :
false;
892 template <
typename T>
898 template <
typename T>
904 template <
typename T>
Exception representing bad access to an Expected instance.
Definition: error.h:218
BadExpectedAccess(Error res)
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:470
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:568
ETCPAL_CONSTEXPR_14 const T & value() const &
Get the underlying value.
Definition: error.h:787
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:623
constexpr const T * operator->() const
Access members of a composite contained value.
Definition: error.h:714
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:542
constexpr Error error() const noexcept
Get the error code as a Error object.
Definition: error.h:838
constexpr const T & operator*() const &
Get the underlying value.
Definition: error.h:734
constexpr bool has_value() const noexcept
Whether this Expected instance contains a valid value. If not, contains an error code.
Definition: error.h:779
constexpr T value_or(U &&def_val) const &
Get the value, or a default value if this Expected contains an error.
Definition: error.h:675
~Expected()
Calls the contained value's destructor if and only if has_value() is true.
Definition: error.h:704
ETCPAL_CONSTEXPR_14 Expected()
Default constructor - enabled if T is default-constructible.
Definition: error.h:494
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:516
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:594
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:640
T value_or(U &&def_val) &&
Get the value, or a default value if this Expected contains an error.
Definition: error.h:684
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:828
T ValueType
The value type.
Definition: error.h:482
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