swap.cpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. #include <catch2/catch.hpp>
  2. #include <tl/expected.hpp>
  3. struct no_throw {
  4. no_throw(std::string i) : i(i) {}
  5. std::string i;
  6. };
  7. struct canthrow_move {
  8. canthrow_move(std::string i) : i(i) {}
  9. canthrow_move(canthrow_move const &) = default;
  10. canthrow_move(canthrow_move &&other) noexcept(false) : i(other.i) {}
  11. canthrow_move &operator=(canthrow_move &&) = default;
  12. std::string i;
  13. };
  14. bool should_throw = false;
  15. #ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
  16. struct willthrow_move {
  17. willthrow_move(std::string i) : i(i) {}
  18. willthrow_move(willthrow_move const &) = default;
  19. willthrow_move(willthrow_move &&other) : i(other.i) {
  20. if (should_throw)
  21. throw 0;
  22. }
  23. willthrow_move &operator=(willthrow_move &&) = default;
  24. std::string i;
  25. };
  26. #endif // TL_EXPECTED_EXCEPTIONS_ENABLED
  27. static_assert(tl::detail::is_swappable<no_throw>::value, "");
  28. template <class T1, class T2> void swap_test() {
  29. std::string s1 = "abcdefghijklmnopqrstuvwxyz";
  30. std::string s2 = "zyxwvutsrqponmlkjihgfedcba";
  31. tl::expected<T1, T2> a{s1};
  32. tl::expected<T1, T2> b{s2};
  33. swap(a, b);
  34. REQUIRE(a->i == s2);
  35. REQUIRE(b->i == s1);
  36. a = s1;
  37. b = tl::unexpected<T2>(s2);
  38. swap(a, b);
  39. REQUIRE(a.error().i == s2);
  40. REQUIRE(b->i == s1);
  41. a = tl::unexpected<T2>(s1);
  42. b = s2;
  43. swap(a, b);
  44. REQUIRE(a->i == s2);
  45. REQUIRE(b.error().i == s1);
  46. a = tl::unexpected<T2>(s1);
  47. b = tl::unexpected<T2>(s2);
  48. swap(a, b);
  49. REQUIRE(a.error().i == s2);
  50. REQUIRE(b.error().i == s1);
  51. a = s1;
  52. b = s2;
  53. a.swap(b);
  54. REQUIRE(a->i == s2);
  55. REQUIRE(b->i == s1);
  56. a = s1;
  57. b = tl::unexpected<T2>(s2);
  58. a.swap(b);
  59. REQUIRE(a.error().i == s2);
  60. REQUIRE(b->i == s1);
  61. a = tl::unexpected<T2>(s1);
  62. b = s2;
  63. a.swap(b);
  64. REQUIRE(a->i == s2);
  65. REQUIRE(b.error().i == s1);
  66. a = tl::unexpected<T2>(s1);
  67. b = tl::unexpected<T2>(s2);
  68. a.swap(b);
  69. REQUIRE(a.error().i == s2);
  70. REQUIRE(b.error().i == s1);
  71. }
  72. #ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
  73. TEST_CASE("swap") {
  74. swap_test<no_throw, no_throw>();
  75. swap_test<no_throw, canthrow_move>();
  76. swap_test<canthrow_move, no_throw>();
  77. std::string s1 = "abcdefghijklmnopqrstuvwxyz";
  78. std::string s2 = "zyxwvutsrqponmlkjihgfedcbaxxx";
  79. tl::expected<no_throw, willthrow_move> a{s1};
  80. tl::expected<no_throw, willthrow_move> b{tl::unexpect, s2};
  81. should_throw = 1;
  82. #ifdef _MSC_VER
  83. //this seems to break catch on GCC and Clang
  84. REQUIRE_THROWS(swap(a, b));
  85. #endif
  86. REQUIRE(a->i == s1);
  87. REQUIRE(b.error().i == s2);
  88. }
  89. #endif // TL_EXPECTED_EXCEPTIONS_ENABLED