Result.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #pragma once
  4. namespace JPH {
  5. /// Helper class that either contains a valid result or an error
  6. template <class Type>
  7. class Result
  8. {
  9. public:
  10. /// Default constructor
  11. Result() { }
  12. /// Copy constructor
  13. Result(const Result<Type> &inRHS)
  14. {
  15. mState = inRHS.mState;
  16. switch (inRHS.mState)
  17. {
  18. case EState::Valid:
  19. new (&mResult) Type (inRHS.mResult);
  20. break;
  21. case EState::Error:
  22. new (&mError) string(inRHS.mError);
  23. break;
  24. case EState::Invalid:
  25. break;
  26. }
  27. }
  28. /// Move constructor
  29. Result(Result<Type> &&inRHS) noexcept
  30. {
  31. mState = inRHS.mState;
  32. switch (inRHS.mState)
  33. {
  34. case EState::Valid:
  35. new (&mResult) Type (move(inRHS.mResult));
  36. break;
  37. case EState::Error:
  38. new (&mError) string(move(inRHS.mError));
  39. break;
  40. case EState::Invalid:
  41. break;
  42. }
  43. inRHS.mState = EState::Invalid;
  44. }
  45. /// Destructor
  46. ~Result() { Clear(); }
  47. /// Copy assignment
  48. Result<Type> & operator = (const Result<Type> &inRHS)
  49. {
  50. Clear();
  51. mState = inRHS.mState;
  52. switch (inRHS.mState)
  53. {
  54. case EState::Valid:
  55. new (&mResult) Type (inRHS.mResult);
  56. break;
  57. case EState::Error:
  58. new (&mError) string(inRHS.mError);
  59. break;
  60. case EState::Invalid:
  61. break;
  62. }
  63. return *this;
  64. }
  65. /// Move assignment
  66. Result<Type> & operator = (Result<Type> &&inRHS) noexcept
  67. {
  68. Clear();
  69. mState = inRHS.mState;
  70. switch (inRHS.mState)
  71. {
  72. case EState::Valid:
  73. new (&mResult) Type (move(inRHS.mResult));
  74. break;
  75. case EState::Error:
  76. new (&mError) string(move(inRHS.mError));
  77. break;
  78. case EState::Invalid:
  79. break;
  80. }
  81. inRHS.mState = EState::Invalid;
  82. return *this;
  83. }
  84. /// Clear result or error
  85. void Clear()
  86. {
  87. switch (mState)
  88. {
  89. case EState::Valid:
  90. mResult.~Type();
  91. break;
  92. case EState::Error:
  93. mError.~string();
  94. break;
  95. case EState::Invalid:
  96. break;
  97. }
  98. mState = EState::Invalid;
  99. }
  100. /// Checks if the result is still uninitialized
  101. bool IsEmpty() const { return mState == EState::Invalid; }
  102. /// Checks if the result is valid
  103. bool IsValid() const { return mState == EState::Valid; }
  104. /// Get the result value
  105. const Type & Get() const { JPH_ASSERT(IsValid()); return mResult; }
  106. /// Set the result value
  107. void Set(const Type &inResult) { Clear(); new (&mResult) Type(inResult); mState = EState::Valid; }
  108. /// Set the result value (move value)
  109. void Set(const Type &&inResult) { Clear(); new (&mResult) Type(move(inResult)); mState = EState::Valid; }
  110. /// Check if we had an error
  111. bool HasError() const { return mState == EState::Error; }
  112. /// Get the error value
  113. const string & GetError() const { JPH_ASSERT(HasError()); return mError; }
  114. /// Set an error value
  115. void SetError(const char *inError) { Clear(); new (&mError) string(inError); mState = EState::Error; }
  116. void SetError(const string &inError) { Clear(); new (&mError) string(inError); mState = EState::Error; }
  117. void SetError(string &&inError) { Clear(); new (&mError) string(move(inError)); mState = EState::Error; }
  118. private:
  119. union
  120. {
  121. Type mResult; ///< The actual result object
  122. string mError; ///< The error description if the result failed
  123. };
  124. /// State of the result
  125. enum class EState : uint8
  126. {
  127. Invalid,
  128. Valid,
  129. Error
  130. };
  131. EState mState = EState::Invalid;
  132. };
  133. } // JPH