Result.h 3.6 KB

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