EtcPal  0.3.0
ETC Platform Abstraction Layer (EtcPal)
View other versions:
error.h
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright 2020 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 Error(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 res);
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 
257 template <typename T>
258 class ExpectedStorageImpl
259 {
260 public:
261  using ValueType = T;
262 
263  // Do not construct or destruct members on construction or destruction
264  ExpectedStorageImpl() {}
265  ~ExpectedStorageImpl() {}
266  explicit ExpectedStorageImpl(bool has_value) : has_value_(has_value) {}
267 
268  void ConstructValue(const ValueType& v) { new (&value_) ValueType(v); }
269  void ConstructValue(ValueType&& v) { new (&value_) ValueType(std::move(v)); }
270  void SetError(etcpal_error_t e) { error_ = e; }
271 
272  void DestructValue() { value_.~ValueType(); }
273 
274  constexpr const ValueType& value() const& { return value_; }
275  ValueType& value() & { return value_; }
276  constexpr const ValueType&& value() const&& { return std::move(value_); }
277  ETCPAL_CONSTEXPR_14 ValueType&& value() && { return std::move(value_); }
278  const ValueType* value_ptr() const { return &value_; }
279  ValueType* value_ptr() { return &value_; }
280 
281  etcpal_error_t error() const { return error_; }
282 
283  bool has_value() const { return has_value_; }
284  void SetHasValue(bool v) { has_value_ = v; }
285 
286 private:
287  bool has_value_{false};
288  union
289  {
290  ValueType value_;
291  etcpal_error_t error_;
292  };
293 };
294 
295 // The ExpectedStorage class provides a way to conditionally delete the copy and/or move
296 // constructors of etcpal::Expected based on the copyability and moveability of the T that we are
297 // being specialized with.
298 //
299 // We provide a generic template where the copy and move constructors are both deleted, then 3
300 // specializations, for (copyable and movable), (copyable and not moveable), and (moveable and not
301 // copyable) respectively.
302 template <typename T, bool IsCopyConstructible, bool IsMoveConstructible>
303 class ExpectedStorage : public ExpectedStorageImpl<T>
304 {
305 public:
306  ExpectedStorage() = default;
307  ~ExpectedStorage() = default;
308 
309  explicit ExpectedStorage(bool has_value) : ExpectedStorageImpl<T>(has_value) {}
310 
311  ExpectedStorage(const ExpectedStorage& other) = delete;
312  ExpectedStorage(ExpectedStorage&& other) = delete;
313 };
314 
315 template <typename T>
316 class ExpectedStorage<T, true, true> : public ExpectedStorageImpl<T>
317 {
318 public:
319  ExpectedStorage() = default;
320  ~ExpectedStorage() = default;
321 
322  explicit ExpectedStorage(bool has_value) : ExpectedStorageImpl<T>(has_value) {}
323 
324  ExpectedStorage(const ExpectedStorage& other) : ExpectedStorageImpl<T>(other.has_value())
325  {
326  if (this->has_value())
327  this->ConstructValue(other.value());
328  else
329  this->SetError(other.error());
330  }
331 
332  ExpectedStorage(ExpectedStorage&& other) : ExpectedStorageImpl<T>(other.has_value())
333  {
334  if (this->has_value())
335  this->ConstructValue(std::move(other.value()));
336  else
337  this->SetError(other.error());
338  }
339 };
340 
341 template <typename T>
342 class ExpectedStorage<T, true, false> : public ExpectedStorageImpl<T>
343 {
344 public:
345  ExpectedStorage() = default;
346  ~ExpectedStorage() = default;
347 
348  explicit ExpectedStorage(bool has_value) : ExpectedStorageImpl<T>(has_value) {}
349 
350  ExpectedStorage(const ExpectedStorage& other) : ExpectedStorageImpl<T>(other.has_value())
351  {
352  if (this->has_value())
353  this->ConstructValue(other.value());
354  else
355  this->SetError(other.error());
356  }
357 
358  ExpectedStorage(ExpectedStorage&& other) = delete;
359 };
360 
361 template <typename T>
362 class ExpectedStorage<T, false, true> : public ExpectedStorageImpl<T>
363 {
364 public:
365  ExpectedStorage() = default;
366  ~ExpectedStorage() = default;
367 
368  explicit ExpectedStorage(bool has_value) : ExpectedStorageImpl<T>(has_value) {}
369 
370  ExpectedStorage(ExpectedStorage const& other) = delete;
371 
372  ExpectedStorage(ExpectedStorage&& other) : ExpectedStorageImpl<T>(other.has_value())
373  {
374  if (this->has_value())
375  this->ConstructValue(std::move(other.value()));
376  else
377  this->SetError(other.error());
378  }
379 };
380 }; // namespace detail
381 
383 
385 // etcpal::Expected
387 
468 template <typename T>
469 class Expected
470 {
471 private:
472  template <typename>
473  friend class Expected;
474 
475 public:
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");
480 
482  using ValueType = T;
483 
484  // Typical ETC library style is to place all function definitions outside the class definition;
485  // however, this gets nasty with these templates so the constructors are an exception here.
486 
487  // clang-format off
488 
493  template <bool B = std::is_default_constructible<T>::value, typename std::enable_if<B, int>::type = 0>
494  ETCPAL_CONSTEXPR_14 Expected() : contained_(true)
495  {
496  contained_.ConstructValue(ValueType());
497  }
498 
503  ETCPAL_CONSTEXPR_14 Expected(const Expected& other) = default;
504 
510 
515  template<typename U>
516  ETCPAL_CONSTEXPR_14 explicit Expected(const Expected<U>& other,
517  ETCPAL_ENABLE_IF_ARG(
518  std::is_constructible<T, const U&>::value &&
519  !std::is_constructible<T, Expected<U>&>::value &&
520  !std::is_constructible<T, Expected<U> && >::value &&
521  !std::is_constructible<T, Expected<U> const & >::value &&
522  !std::is_constructible<T, Expected<U> const && >::value &&
523  !std::is_convertible< Expected<U> & , T>::value &&
524  !std::is_convertible< Expected<U> &&, T>::value &&
525  !std::is_convertible< Expected<U> const & , T>::value &&
526  !std::is_convertible< Expected<U> const &&, T>::value &&
527  !std::is_convertible<const U&, T>::value
528  ))
529  : contained_(other.has_value())
530  {
531  if (has_value())
532  contained_.ConstructValue(T{other.contained_.value()});
533  else
534  contained_.SetError(other.contained_.error());
535  }
536 
541  template<typename U>
543  ETCPAL_ENABLE_IF_ARG(
544  std::is_constructible<T, const U&>::value &&
545  !std::is_constructible<T, Expected<U> & >::value &&
546  !std::is_constructible<T, Expected<U> && >::value &&
547  !std::is_constructible<T, Expected<U> const & >::value &&
548  !std::is_constructible<T, Expected<U> const && >::value &&
549  !std::is_convertible< Expected<U> & , T>::value &&
550  !std::is_convertible< Expected<U> &&, T>::value &&
551  !std::is_convertible< Expected<U> const &, T>::value &&
552  !std::is_convertible< Expected<U> const &&, T>::value &&
553  std::is_convertible<const U&, T>::value
554  ))
555  : contained_(other.has_value())
556  {
557  if (has_value())
558  contained_.ConstructValue(other.contained_.value());
559  else
560  contained_.SetError(other.contained_.error());
561  }
562 
567  template<typename U>
569  ETCPAL_ENABLE_IF_ARG(
570  std::is_constructible<T, U>::value &&
571  !std::is_constructible<T, Expected<U> & >::value &&
572  !std::is_constructible<T, Expected<U> && >::value &&
573  !std::is_constructible<T, Expected<U> const & >::value &&
574  !std::is_constructible<T, Expected<U> const && >::value &&
575  !std::is_convertible< Expected<U> & , T>::value &&
576  !std::is_convertible< Expected<U> &&, T>::value &&
577  !std::is_convertible< Expected<U> const & , T>::value &&
578  !std::is_convertible< Expected<U> const &&, T>::value &&
579  !std::is_convertible<U, T>::value
580  ))
581  : contained_(other.has_value())
582  {
583  if (has_value())
584  contained_.ConstructValue(T{std::move(other.contained_.value())});
585  else
586  contained_.SetError(other.contained_.error());
587  }
588 
593  template<typename U>
595  ETCPAL_ENABLE_IF_ARG(
596  std::is_constructible<T, U>::value &&
597  !std::is_constructible<T, Expected<U> & >::value &&
598  !std::is_constructible<T, Expected<U> && >::value &&
599  !std::is_constructible<T, Expected<U> const & >::value &&
600  !std::is_constructible<T, Expected<U> const && >::value &&
601  !std::is_convertible< Expected<U> & , T>::value &&
602  !std::is_convertible< Expected<U> &&, T>::value &&
603  !std::is_convertible< Expected<U> const & , T>::value &&
604  !std::is_convertible< Expected<U> const &&, T>::value &&
605  std::is_convertible<U, T>::value
606  ))
607  : contained_(other.has_value())
608  {
609  if (has_value())
610  contained_.ConstructValue(std::move(other.contained_.value()));
611  else
612  contained_.SetError(other.contained_.error());
613  }
614 
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)
627  : contained_(true)
628  {
629  contained_.ConstructValue(T{std::forward<U>(value)});
630  }
631 
639  template <typename U = T>
640  ETCPAL_CONSTEXPR_14 Expected(U&& value, ETCPAL_ENABLE_IF_ARG(std::is_constructible<T, U&&>::value &&
641  std::is_convertible<U&&, T>::value
642  )) noexcept(std::is_nothrow_move_constructible<U>::value)
643  : contained_(true)
644  {
645  contained_.ConstructValue(std::forward<U>(value));
646  }
647 
648  // clang-format on
649 
650  // Always implicit by design
652  ~Expected();
653 
654  constexpr const T* operator->() const;
655  T* operator->();
656  constexpr const T& operator*() const&;
657  T& operator*() &;
658  constexpr const T&& operator*() const&&;
659  ETCPAL_CONSTEXPR_14 T&& operator*() &&;
660  constexpr explicit operator bool() const noexcept;
661  constexpr bool has_value() const noexcept;
662  ETCPAL_CONSTEXPR_14 const T& value() const&;
663  T& value() &;
664  ETCPAL_CONSTEXPR_14 const T&& value() const&&;
665  ETCPAL_CONSTEXPR_14 T&& value() &&;
666  constexpr etcpal_error_t error_code() const noexcept;
667  constexpr Error error() const noexcept;
668 
669  // clang-format off
670 
673  template <typename U,
674  ETCPAL_ENABLE_IF_TEMPLATE(std::is_copy_constructible<T>::value && std::is_convertible<U&&, T>::value)>
675  constexpr T value_or(U&& def_val) const&
676  {
677  return has_value() ? contained_.value() : static_cast<T>(std::forward<U>(def_val));
678  }
679 
682  template <typename U,
683  ETCPAL_ENABLE_IF_TEMPLATE(std::is_move_constructible<T>::value && std::is_convertible<U&&, T>::value)>
684  T value_or(U&& def_val) &&
685  {
686  return has_value() ? contained_.value() : static_cast<T>(std::forward<U>(def_val));
687  }
688 
689  // clang-format on
690 
691 private:
692  detail::ExpectedStorage<T, std::is_copy_constructible<T>::value, std::is_move_constructible<T>::value> contained_;
693 }; // namespace etcpal
694 
696 template <typename T>
698 {
699  contained_.SetError(error);
700 }
701 
703 template <typename T>
705 {
706  if (has_value())
707  contained_.DestructValue();
708 }
709 
713 template <typename T>
714 constexpr const T* Expected<T>::operator->() const
715 {
716  // Comma syntax is to satisfy C++11 requirements for constexpr
717  return assert(has_value()), contained_.value_ptr();
718 }
719 
723 template <typename T>
725 {
726  // Comma syntax is to satisfy C++11 requirements for constexpr
727  return assert(has_value()), contained_.value_ptr();
728 }
729 
733 template <typename T>
734 constexpr const T& Expected<T>::operator*() const&
735 {
736  // Comma syntax is to satisfy C++11 requirements for constexpr
737  return assert(has_value()), contained_.value();
738 }
739 
743 template <typename T>
745 {
746  // Comma syntax is to satisfy C++11 requirements for constexpr
747  return assert(has_value()), contained_.value();
748 }
749 
753 template <typename T>
754 constexpr const T&& Expected<T>::operator*() const&&
755 {
756  // Comma syntax is to satisfy C++11 requirements for constexpr
757  return assert(has_value()), std::move(contained_.value());
758 }
759 
763 template <typename T>
765 {
766  // Comma syntax is to satisfy C++11 requirements for constexpr
767  return assert(has_value()), std::move(contained_.value());
768 }
769 
771 template <typename T>
772 constexpr Expected<T>::operator bool() const noexcept
773 {
774  return has_value();
775 }
776 
778 template <typename T>
779 constexpr bool Expected<T>::has_value() const noexcept
780 {
781  return contained_.has_value();
782 }
783 
786 template <typename T>
788 {
789  if (!has_value())
790  ETCPAL_THROW(BadExpectedAccess(contained_.error()));
791  return contained_.value();
792 }
793 
796 template <typename T>
798 {
799  if (!has_value())
800  ETCPAL_THROW(BadExpectedAccess(contained_.error()));
801  return contained_.value();
802 }
803 
806 template <typename T>
808 {
809  if (!has_value())
810  ETCPAL_THROW(BadExpectedAccess(contained_.error()));
811  return std::move(contained_.value());
812 }
813 
816 template <typename T>
818 {
819  if (!has_value())
820  ETCPAL_THROW(BadExpectedAccess(contained_.error()));
821  return std::move(contained_.value());
822 }
823 
827 template <typename T>
828 constexpr etcpal_error_t Expected<T>::error_code() const noexcept
829 {
830  // Comma syntax is to satisfy C++11 requirements for constexpr
831  return assert(!has_value()), contained_.error();
832 }
833 
837 template <typename T>
838 constexpr Error Expected<T>::error() const noexcept
839 {
840  // Comma syntax is to satisfy C++11 requirements for constexpr
841  return assert(!has_value()), contained_.error();
842 }
843 
846 
849 
850 template <typename T1, typename T2>
851 constexpr bool operator==(const Expected<T1>& x, const Expected<T2>& y)
852 {
853  return bool(x) != bool(y) ? false : bool(x) == false ? x.error_code() == y.error_code() : *x == *y;
854 }
855 
856 template <typename T1, typename T2>
857 constexpr bool operator!=(const Expected<T1>& x, const Expected<T2>& y)
858 {
859  return !(x == y);
860 }
861 
862 template <typename T1, typename T2>
863 constexpr bool operator==(const Expected<T1>& x, const T2& v)
864 {
865  return bool(x) ? *x == v : false;
866 }
867 
868 template <typename T1, typename T2>
869 constexpr bool operator==(const T2& v, const Expected<T1>& x)
870 {
871  return bool(x) ? v == *x : false;
872 }
873 
874 template <typename T1, typename T2>
875 constexpr bool operator!=(const Expected<T1>& x, const T2& v)
876 {
877  return bool(x) ? *x != v : true;
878 }
879 
880 template <typename T1, typename T2>
881 constexpr bool operator!=(const T2& v, const Expected<T1>& x)
882 {
883  return bool(x) ? v != *x : true;
884 }
885 
886 template <typename T>
887 constexpr bool operator==(const Expected<T>& x, etcpal_error_t e)
888 {
889  return (!x) ? x.error_code() == e : false;
890 }
891 
892 template <typename T>
893 constexpr bool operator==(etcpal_error_t e, const Expected<T>& x)
894 {
895  return (x == e);
896 }
897 
898 template <typename T>
899 constexpr bool operator!=(const Expected<T>& x, etcpal_error_t e)
900 {
901  return !(x == e);
902 }
903 
904 template <typename T>
905 constexpr bool operator!=(etcpal_error_t e, const Expected<T>& x)
906 {
907  return !(x == e);
908 }
909 
912 
913 }; // namespace etcpal
914 
915 #endif // ETCPAL_CPP_ERROR_H_
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