move.pass.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. //===----------------------------------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. // UNSUPPORTED: c++98, c++03, c++11, c++14
  9. // <optional>
  10. // optional<T>& operator=(optional<T>&& rhs)
  11. // noexcept(is_nothrow_move_assignable<T>::value &&
  12. // is_nothrow_move_constructible<T>::value); // constexpr in C++20
  13. #include <optional>
  14. #include <cassert>
  15. #include <type_traits>
  16. #include <utility>
  17. #include "test_macros.h"
  18. #include "archetypes.h"
  19. using std::optional;
  20. struct X
  21. {
  22. static bool throw_now;
  23. static int alive;
  24. X() { ++alive; }
  25. X(X&&)
  26. {
  27. if (throw_now)
  28. TEST_THROW(6);
  29. ++alive;
  30. }
  31. X& operator=(X&&)
  32. {
  33. if (throw_now)
  34. TEST_THROW(42);
  35. return *this;
  36. }
  37. ~X() { assert(alive > 0); --alive; }
  38. };
  39. struct Y {};
  40. bool X::throw_now = false;
  41. int X::alive = 0;
  42. template <class Tp>
  43. constexpr bool assign_empty(optional<Tp>&& lhs) {
  44. optional<Tp> rhs;
  45. lhs = std::move(rhs);
  46. return !lhs.has_value() && !rhs.has_value();
  47. }
  48. template <class Tp>
  49. constexpr bool assign_value(optional<Tp>&& lhs) {
  50. optional<Tp> rhs(101);
  51. lhs = std::move(rhs);
  52. return lhs.has_value() && rhs.has_value() && *lhs == Tp{101};
  53. }
  54. int main(int, char**)
  55. {
  56. {
  57. static_assert(std::is_nothrow_move_assignable<optional<int>>::value, "");
  58. optional<int> opt;
  59. constexpr optional<int> opt2;
  60. opt = std::move(opt2);
  61. static_assert(static_cast<bool>(opt2) == false, "");
  62. assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
  63. }
  64. {
  65. optional<int> opt;
  66. constexpr optional<int> opt2(2);
  67. opt = std::move(opt2);
  68. static_assert(static_cast<bool>(opt2) == true, "");
  69. static_assert(*opt2 == 2, "");
  70. assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
  71. assert(*opt == *opt2);
  72. }
  73. {
  74. optional<int> opt(3);
  75. constexpr optional<int> opt2;
  76. opt = std::move(opt2);
  77. static_assert(static_cast<bool>(opt2) == false, "");
  78. assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
  79. }
  80. {
  81. using T = TestTypes::TestType;
  82. T::reset();
  83. optional<T> opt(3);
  84. optional<T> opt2;
  85. assert(T::alive == 1);
  86. opt = std::move(opt2);
  87. assert(T::alive == 0);
  88. assert(static_cast<bool>(opt2) == false);
  89. assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
  90. }
  91. {
  92. optional<int> opt(3);
  93. constexpr optional<int> opt2(2);
  94. opt = std::move(opt2);
  95. static_assert(static_cast<bool>(opt2) == true, "");
  96. static_assert(*opt2 == 2, "");
  97. assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
  98. assert(*opt == *opt2);
  99. }
  100. {
  101. using O = optional<int>;
  102. #if TEST_STD_VER > 17
  103. LIBCPP_STATIC_ASSERT(assign_empty(O{42}), "");
  104. LIBCPP_STATIC_ASSERT(assign_value(O{42}), "");
  105. #endif
  106. assert(assign_empty(O{42}));
  107. assert(assign_value(O{42}));
  108. }
  109. {
  110. using O = optional<TrivialTestTypes::TestType>;
  111. #if TEST_STD_VER > 17
  112. LIBCPP_STATIC_ASSERT(assign_empty(O{42}), "");
  113. LIBCPP_STATIC_ASSERT(assign_value(O{42}), "");
  114. #endif
  115. assert(assign_empty(O{42}));
  116. assert(assign_value(O{42}));
  117. }
  118. #ifndef TEST_HAS_NO_EXCEPTIONS
  119. {
  120. static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, "");
  121. X::alive = 0;
  122. X::throw_now = false;
  123. optional<X> opt;
  124. optional<X> opt2(X{});
  125. assert(X::alive == 1);
  126. assert(static_cast<bool>(opt2) == true);
  127. try
  128. {
  129. X::throw_now = true;
  130. opt = std::move(opt2);
  131. assert(false);
  132. }
  133. catch (int i)
  134. {
  135. assert(i == 6);
  136. assert(static_cast<bool>(opt) == false);
  137. }
  138. assert(X::alive == 1);
  139. }
  140. assert(X::alive == 0);
  141. {
  142. static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, "");
  143. X::throw_now = false;
  144. optional<X> opt(X{});
  145. optional<X> opt2(X{});
  146. assert(X::alive == 2);
  147. assert(static_cast<bool>(opt2) == true);
  148. try
  149. {
  150. X::throw_now = true;
  151. opt = std::move(opt2);
  152. assert(false);
  153. }
  154. catch (int i)
  155. {
  156. assert(i == 42);
  157. assert(static_cast<bool>(opt) == true);
  158. }
  159. assert(X::alive == 2);
  160. }
  161. assert(X::alive == 0);
  162. #endif // TEST_HAS_NO_EXCEPTIONS
  163. {
  164. static_assert(std::is_nothrow_move_assignable<optional<Y>>::value, "");
  165. }
  166. {
  167. struct ThrowsMove {
  168. ThrowsMove() noexcept {}
  169. ThrowsMove(ThrowsMove const&) noexcept {}
  170. ThrowsMove(ThrowsMove &&) noexcept(false) {}
  171. ThrowsMove& operator=(ThrowsMove const&) noexcept { return *this; }
  172. ThrowsMove& operator=(ThrowsMove &&) noexcept { return *this; }
  173. };
  174. static_assert(!std::is_nothrow_move_assignable<optional<ThrowsMove>>::value, "");
  175. struct ThrowsMoveAssign {
  176. ThrowsMoveAssign() noexcept {}
  177. ThrowsMoveAssign(ThrowsMoveAssign const&) noexcept {}
  178. ThrowsMoveAssign(ThrowsMoveAssign &&) noexcept {}
  179. ThrowsMoveAssign& operator=(ThrowsMoveAssign const&) noexcept { return *this; }
  180. ThrowsMoveAssign& operator=(ThrowsMoveAssign &&) noexcept(false) { return *this; }
  181. };
  182. static_assert(!std::is_nothrow_move_assignable<optional<ThrowsMoveAssign>>::value, "");
  183. struct NoThrowMove {
  184. NoThrowMove() noexcept(false) {}
  185. NoThrowMove(NoThrowMove const&) noexcept(false) {}
  186. NoThrowMove(NoThrowMove &&) noexcept {}
  187. NoThrowMove& operator=(NoThrowMove const&) noexcept { return *this; }
  188. NoThrowMove& operator=(NoThrowMove&&) noexcept { return *this; }
  189. };
  190. static_assert(std::is_nothrow_move_assignable<optional<NoThrowMove>>::value, "");
  191. }
  192. return 0;
  193. }