issues.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. #include <catch2/catch.hpp>
  2. #include <tl/expected.hpp>
  3. #include <string>
  4. #include <memory>
  5. using std::string;
  6. tl::expected<int, string> getInt3(int val) { return val; }
  7. tl::expected<int, string> getInt2(int val) { return val; }
  8. tl::expected<int, string> getInt1() { return getInt2(5).and_then(getInt3); }
  9. TEST_CASE("Issue 1", "[issues.1]") { getInt1(); }
  10. tl::expected<int, int> operation1() { return 42; }
  11. tl::expected<std::string, int> operation2(int const val) { (void)val; return "Bananas"; }
  12. TEST_CASE("Issue 17", "[issues.17]") {
  13. auto const intermediate_result = operation1();
  14. intermediate_result.and_then(operation2);
  15. }
  16. struct a {};
  17. struct b : a {};
  18. auto doit() -> tl::expected<std::unique_ptr<b>, int> {
  19. return tl::make_unexpected(0);
  20. }
  21. TEST_CASE("Issue 23", "[issues.23]") {
  22. tl::expected<std::unique_ptr<a>, int> msg = doit();
  23. REQUIRE(!msg.has_value());
  24. }
  25. TEST_CASE("Issue 26", "[issues.26]") {
  26. tl::expected<a, int> exp = tl::expected<b, int>(tl::unexpect, 0);
  27. REQUIRE(!exp.has_value());
  28. }
  29. struct foo {
  30. foo() = default;
  31. foo(foo &) = delete;
  32. foo(foo &&){};
  33. };
  34. TEST_CASE("Issue 29", "[issues.29]") {
  35. std::vector<foo> v;
  36. v.emplace_back();
  37. tl::expected<std::vector<foo>, int> ov = std::move(v);
  38. REQUIRE(ov->size() == 1);
  39. }
  40. tl::expected<int, std::string> error() {
  41. return tl::make_unexpected(std::string("error1 "));
  42. }
  43. std::string maperror(std::string s) { return s + "maperror "; }
  44. TEST_CASE("Issue 30", "[issues.30]") {
  45. error().map_error(maperror);
  46. }
  47. struct i31{
  48. int i;
  49. };
  50. TEST_CASE("Issue 31", "[issues.31]") {
  51. const tl::expected<i31, int> a = i31{42};
  52. (void)a->i;
  53. tl::expected< void, std::string > result;
  54. tl::expected< void, std::string > result2 = result;
  55. result2 = result;
  56. }
  57. TEST_CASE("Issue 33", "[issues.33]") {
  58. tl::expected<void, int> res {tl::unexpect, 0};
  59. REQUIRE(!res);
  60. res = res.map_error([](int i) { (void)i; return 42; });
  61. REQUIRE(res.error() == 42);
  62. }
  63. tl::expected<void, std::string> voidWork() { return {}; }
  64. tl::expected<int, std::string> work2() { return 42; }
  65. void errorhandling(std::string){}
  66. TEST_CASE("Issue 34", "[issues.34]") {
  67. tl::expected <int, std::string> result = voidWork ()
  68. .and_then (work2);
  69. result.map_error ([&] (std::string result) {errorhandling (result);});
  70. }
  71. struct non_copyable {
  72. non_copyable(non_copyable&&) = default;
  73. non_copyable(non_copyable const&) = delete;
  74. non_copyable() = default;
  75. };
  76. TEST_CASE("Issue 42", "[issues.42]") {
  77. tl::expected<non_copyable,int>{}.map([](non_copyable) {});
  78. }
  79. TEST_CASE("Issue 43", "[issues.43]") {
  80. auto result = tl::expected<void, std::string>{};
  81. result = tl::make_unexpected(std::string{ "foo" });
  82. }
  83. #if !(__GNUC__ <= 5)
  84. #include <memory>
  85. using MaybeDataPtr = tl::expected<int, std::unique_ptr<int>>;
  86. MaybeDataPtr test(int i) noexcept
  87. {
  88. return std::move(i);
  89. }
  90. MaybeDataPtr test2(int i) noexcept
  91. {
  92. return std::move(i);
  93. }
  94. TEST_CASE("Issue 49", "[issues.49]") {
  95. auto m = test(10)
  96. .and_then(test2);
  97. }
  98. #endif
  99. tl::expected<int, std::unique_ptr<std::string>> func()
  100. {
  101. return 1;
  102. }
  103. TEST_CASE("Issue 61", "[issues.61]") {
  104. REQUIRE(func().value() == 1);
  105. }
  106. struct move_tracker {
  107. int moved = 0;
  108. move_tracker() = default;
  109. move_tracker(move_tracker const &other) noexcept {};
  110. move_tracker(move_tracker &&orig) noexcept
  111. : moved(orig.moved + 1) {}
  112. move_tracker &
  113. operator=(move_tracker const &other) noexcept {};
  114. move_tracker &operator=(move_tracker &&orig) noexcept {
  115. moved = orig.moved + 1;
  116. return *this;
  117. }
  118. };
  119. TEST_CASE("Issue 122", "[issues.122]") {
  120. tl::expected<move_tracker, int> res;
  121. res.emplace();
  122. REQUIRE(res.value().moved == 0);
  123. }
  124. #ifdef __cpp_deduction_guides
  125. TEST_CASE("Issue 89", "[issues.89]") {
  126. auto s = tl::unexpected("Some string");
  127. REQUIRE(s.value() == std::string("Some string"));
  128. }
  129. #endif
  130. struct S {
  131. int i = 0;
  132. int j = 0;
  133. S(int i) : i(i) {}
  134. S(int i, int j) : i(i), j(j) {}
  135. };
  136. TEST_CASE("Issue 107", "[issues.107]") {
  137. tl::expected<int, S> ex1(tl::unexpect, 2);
  138. tl::expected<int, S> ex2(tl::unexpect, 2, 2);
  139. REQUIRE(ex1.error().i == 2);
  140. REQUIRE(ex1.error().j == 0);
  141. REQUIRE(ex2.error().i == 2);
  142. REQUIRE(ex2.error().j == 2);
  143. }
  144. TEST_CASE("Issue 129", "[issues.129]") {
  145. tl::expected<std::unique_ptr<int>, int> x1 {std::unique_ptr<int>(new int(4))};
  146. tl::expected<std::unique_ptr<int>, int> y1 {std::unique_ptr<int>(new int(2))};
  147. x1 = std::move(y1);
  148. REQUIRE(**x1 == 2);
  149. }