experimental-p0709a.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /* Unit testing for outcomes
  2. (C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (7 commits)
  3. Boost Software License - Version 1.0 - August 17th, 2003
  4. Permission is hereby granted, free of charge, to any person or organization
  5. obtaining a copy of the software and accompanying documentation covered by
  6. this license (the "Software") to use, reproduce, display, distribute,
  7. execute, and transmit the Software, and to prepare derivative works of the
  8. Software, and to permit third-parties to whom the Software is furnished to
  9. do so, all subject to the following:
  10. The copyright notices in the Software and this entire statement, including
  11. the above license grant, this restriction and the following disclaimer,
  12. must be included in all copies of the Software, in whole or in part, and
  13. all derivative works of the Software, unless such copies or derivative
  14. works are solely in the form of machine-executable object code generated by
  15. a source language processor.
  16. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
  19. SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
  20. FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
  21. ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  22. DEALINGS IN THE SOFTWARE.
  23. */
  24. #include <boost/outcome/experimental/status_result.hpp>
  25. #include <climits> // for INT_MAX
  26. #include <cstdio>
  27. // status_code<erased<intptr_t>>
  28. using error = BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::error;
  29. // Outcome's result must be told when it is dealing with an erased status code
  30. template <class T, class E> using result = BOOST_OUTCOME_V2_NAMESPACE::experimental::status_result<T, E, BOOST_OUTCOME_V2_NAMESPACE::policy::all_narrow>;
  31. enum class arithmetic_errc
  32. {
  33. success,
  34. divide_by_zero,
  35. integer_divide_overflows,
  36. not_integer_division
  37. };
  38. class _arithmetic_errc_domain;
  39. using arithmetic_errc_error = BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<_arithmetic_errc_domain>;
  40. class _arithmetic_errc_domain : public BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code_domain
  41. {
  42. using _base = BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code_domain;
  43. public:
  44. using value_type = arithmetic_errc;
  45. constexpr explicit _arithmetic_errc_domain(typename _base::unique_id_type id = 0x290f170194f0c6c7) noexcept : _base(id) {}
  46. static inline constexpr const _arithmetic_errc_domain &get();
  47. virtual _base::string_ref name() const noexcept override final // NOLINT
  48. {
  49. static string_ref v("arithmetic error domain");
  50. return v; // NOLINT
  51. }
  52. protected:
  53. virtual bool _do_failure(const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<void> &code) const noexcept override final // NOLINT
  54. {
  55. assert(code.domain() == *this); // NOLINT
  56. const auto &c1 = static_cast<const arithmetic_errc_error &>(code); // NOLINT
  57. return c1.value() != arithmetic_errc::success;
  58. }
  59. virtual bool _do_equivalent(const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<void> &, const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<void> &) const noexcept override final { return false; } // NOLINT
  60. virtual BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::generic_code _generic_code(const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<void> &) const noexcept override final { return {}; } // NOLINT
  61. virtual _base::string_ref _do_message(const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<void> &code) const noexcept override final // NOLINT
  62. {
  63. assert(code.domain() == *this); // NOLINT
  64. const auto &c1 = static_cast<const arithmetic_errc_error &>(code); // NOLINT
  65. switch(c1.value())
  66. {
  67. case arithmetic_errc::success:
  68. return _base::string_ref("success");
  69. case arithmetic_errc::divide_by_zero:
  70. return _base::string_ref("divide by zero");
  71. case arithmetic_errc::integer_divide_overflows:
  72. return _base::string_ref("integer divide overflows");
  73. case arithmetic_errc::not_integer_division:
  74. return _base::string_ref("not integer division");
  75. }
  76. return _base::string_ref("unknown");
  77. }
  78. BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::status_code<void> &) const override final { abort(); } // NOLINT
  79. };
  80. constexpr _arithmetic_errc_domain arithmetic_errc_domain;
  81. inline constexpr const _arithmetic_errc_domain &_arithmetic_errc_domain::get()
  82. {
  83. return arithmetic_errc_domain;
  84. }
  85. // Tell status code about the available implicit conversion
  86. inline arithmetic_errc_error make_status_code(arithmetic_errc e)
  87. {
  88. return arithmetic_errc_error(BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::in_place, e);
  89. }
  90. BOOST_OUTCOME_V2_NAMESPACE_BEGIN
  91. namespace trait
  92. {
  93. // Tell Outcome that arithmetic_errc is convertible into std::error
  94. template <> struct is_error_type_enum<error, arithmetic_errc>
  95. {
  96. static constexpr bool value = true;
  97. };
  98. }
  99. BOOST_OUTCOME_V2_NAMESPACE_END
  100. // And tell Outcome how to perform the implicit conversion
  101. inline error make_error_code(arithmetic_errc e)
  102. {
  103. return arithmetic_errc_error(BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::in_place, e);
  104. }
  105. result<int, error> safe_divide(int i, int j)
  106. {
  107. if(j == 0)
  108. {
  109. return arithmetic_errc::divide_by_zero;
  110. }
  111. if(i == INT_MIN && j == -1)
  112. {
  113. return arithmetic_errc::integer_divide_overflows;
  114. }
  115. if(i % j != 0)
  116. {
  117. return arithmetic_errc::not_integer_division;
  118. }
  119. return i / j;
  120. }
  121. int caller2(int i, int j)
  122. {
  123. auto r = safe_divide(i, j);
  124. if(r)
  125. {
  126. return r.value();
  127. }
  128. if(r.error() == arithmetic_errc::divide_by_zero)
  129. {
  130. return 0;
  131. }
  132. if(r.error() == arithmetic_errc::not_integer_division)
  133. {
  134. return i / j; // ignore
  135. }
  136. if(r.error() == arithmetic_errc::integer_divide_overflows)
  137. {
  138. return INT_MIN;
  139. }
  140. return 0;
  141. }
  142. int main()
  143. {
  144. printf("%d\n", caller2(5, 6)); // NOLINT
  145. return 0;
  146. }