16 #ifndef WPIUTIL_WPI_ERROROR_H
17 #define WPIUTIL_WPI_ERROROR_H
19 #include "wpi/AlignOf.h"
21 #include <system_error>
22 #include <type_traits>
58 template <
class OtherT>
friend class ErrorOr;
60 static const bool isRef = std::is_reference<T>::value;
62 using wrap = std::reference_wrapper<typename std::remove_reference<T>::type>;
65 using storage_type =
typename std::conditional<isRef, wrap, T>::type;
68 using reference =
typename std::remove_reference<T>::type &;
69 using const_reference =
const typename std::remove_reference<T>::type &;
70 using pointer =
typename std::remove_reference<T>::type *;
71 using const_pointer =
const typename std::remove_reference<T>::type *;
76 typename std::enable_if<std::is_error_code_enum<E>::value ||
77 std::is_error_condition_enum<E>::value,
78 void *>::type =
nullptr)
80 new (getErrorStorage()) std::error_code(make_error_code(ErrorCode));
83 ErrorOr(std::error_code EC) : HasError(
true) {
84 new (getErrorStorage()) std::error_code(EC);
87 template <
class OtherT>
89 typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
92 new (getStorage()) storage_type(std::forward<OtherT>(Val));
99 template <
class OtherT>
102 typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * =
104 copyConstruct(Other);
107 template <
class OtherT>
110 typename std::enable_if<
111 !std::is_convertible<OtherT, const T &>::value>::type * =
nullptr) {
112 copyConstruct(Other);
116 moveConstruct(std::move(Other));
119 template <
class OtherT>
122 typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * =
124 moveConstruct(std::move(Other));
129 template <
class OtherT>
132 typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * =
134 moveConstruct(std::move(Other));
143 moveAssign(std::move(Other));
149 getStorage()->~storage_type();
153 explicit operator bool()
const {
157 reference get() {
return *getStorage(); }
158 const_reference get()
const {
return const_cast<ErrorOr<T> *
>(
this)->get(); }
160 std::error_code getError()
const {
161 return HasError ? *getErrorStorage() : std::error_code();
164 pointer operator ->() {
165 return toPointer(getStorage());
168 const_pointer operator->()
const {
return toPointer(getStorage()); }
170 reference operator *() {
171 return *getStorage();
174 const_reference operator*()
const {
return *getStorage(); }
177 template <
class OtherT>
178 void copyConstruct(
const ErrorOr<OtherT> &Other) {
179 if (!Other.HasError) {
182 new (getStorage()) storage_type(*Other.getStorage());
186 new (getErrorStorage()) std::error_code(Other.getError());
191 static bool compareThisIfSameType(
const T1 &a,
const T1 &b) {
195 template <
class T1,
class T2>
196 static bool compareThisIfSameType(
const T1 &a,
const T2 &b) {
200 template <
class OtherT>
201 void copyAssign(
const ErrorOr<OtherT> &Other) {
202 if (compareThisIfSameType(*
this, Other))
206 new (
this) ErrorOr(Other);
209 template <
class OtherT>
210 void moveConstruct(ErrorOr<OtherT> &&Other) {
211 if (!Other.HasError) {
214 new (getStorage()) storage_type(std::move(*Other.getStorage()));
218 new (getErrorStorage()) std::error_code(Other.getError());
222 template <
class OtherT>
223 void moveAssign(ErrorOr<OtherT> &&Other) {
224 if (compareThisIfSameType(*
this, Other))
228 new (
this) ErrorOr(std::move(Other));
231 pointer toPointer(pointer Val) {
235 const_pointer toPointer(const_pointer Val)
const {
return Val; }
237 pointer toPointer(wrap *Val) {
241 const_pointer toPointer(
const wrap *Val)
const {
return &Val->get(); }
243 storage_type *getStorage() {
244 assert(!HasError &&
"Cannot get value when an error exists!");
245 return reinterpret_cast<storage_type*>(TStorage.buffer);
248 const storage_type *getStorage()
const {
249 assert(!HasError &&
"Cannot get value when an error exists!");
250 return reinterpret_cast<const storage_type*>(TStorage.buffer);
253 std::error_code *getErrorStorage() {
254 assert(HasError &&
"Cannot get error when a value exists!");
255 return reinterpret_cast<std::error_code *>(ErrorStorage.buffer);
258 const std::error_code *getErrorStorage()
const {
259 return const_cast<ErrorOr<T> *
>(
this)->getErrorStorage();
263 AlignedCharArrayUnion<storage_type> TStorage;
264 AlignedCharArrayUnion<std::error_code> ErrorStorage;
269 template <
class T,
class E>
270 typename std::enable_if<std::is_error_code_enum<E>::value ||
271 std::is_error_condition_enum<E>::value,
273 operator==(
const ErrorOr<T> &Err, E Code) {
274 return Err.getError() == Code;
279 #endif // LLVM_SUPPORT_ERROROR_H