fork(1) download
  1. #include <exception>
  2. #include <stdexcept>
  3. #include <cstddef>
  4. #include <cstdint>
  5. #include <cstdlib>
  6.  
  7. using error_type = std::exception_ptr;
  8.  
  9. struct ResultBase
  10. {
  11. bool hasError() const
  12. {
  13. return *reinterpret_cast<const bool*>(this);
  14. }
  15.  
  16. std::exception_ptr error() const
  17. {
  18. return *reinterpret_cast<const error_type*>(
  19. reinterpret_cast<const char*>(this)
  20. + sizeof(std::max_align_t));
  21. }
  22.  
  23. protected:
  24. ResultBase() { }
  25. };
  26.  
  27. template <class T>
  28. struct Result : ResultBase
  29. {
  30. Result(error_type error)
  31. : mHasError(true) { new (&mError) error_type(error); }
  32.  
  33. Result(T value)
  34. : mHasError(false) { new (&mValue) T(value); }
  35.  
  36. ~Result()
  37. {
  38. if (mHasError)
  39. mError.~error_type();
  40. else
  41. mValue.~T();
  42. }
  43.  
  44. void setError(error_type error)
  45. {
  46. if (mHasError) {
  47. mError = error;
  48. } else {
  49. mValue.~T();
  50. new (&mError) error_type(error);
  51. mHasError = true;
  52. }
  53. }
  54.  
  55. void setValue(T value)
  56. {
  57. if (mHasError) {
  58. mError.~error_type();
  59. new (&mValue) T(value);
  60. mHasError = false;
  61. } else {
  62. mValue = value;
  63. }
  64. }
  65.  
  66. private:
  67. union {
  68. bool mHasError;
  69. std::max_align_t mAligner;
  70. };
  71. union {
  72. error_type mError;
  73. T mValue;
  74. };
  75. };
  76.  
  77. static_assert(std::is_standard_layout<Result<int>>::value, "");
  78.  
  79. void check(bool condition)
  80. {
  81. if (!condition) std::terminate();
  82. }
  83.  
  84. void f(const ResultBase& alias, Result<int>& r)
  85. {
  86. check(!alias.hasError());
  87.  
  88. r.setError(std::exception_ptr());
  89. check(alias.hasError());
  90. check(alias.error() == nullptr);
  91.  
  92. r.setValue(1);
  93. check(!alias.hasError());
  94.  
  95. r.setError(std::make_exception_ptr(std::runtime_error("!")));
  96. check(alias.hasError());
  97. check(alias.error() != nullptr);
  98. }
  99.  
  100. int main()
  101. {
  102. Result<int> r(0);
  103. f(r, r);
  104. }
  105.  
Success #stdin #stdout 0s 3456KB
stdin
Standard input is empty
stdout
Standard output is empty