copy.pass.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. // -*- C++ -*-
  2. //===----------------------------------------------------------------------===//
  3. //
  4. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  5. // See https://llvm.org/LICENSE.txt for license information.
  6. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  7. //
  8. //===----------------------------------------------------------------------===//
  9. // UNSUPPORTED: c++98, c++03, c++11, c++14
  10. // XFAIL: dylib-has-no-bad_variant_access
  11. // <variant>
  12. // template <class ...Types> class variant;
  13. // variant(variant const&); // constexpr in C++20
  14. #include <cassert>
  15. #include <type_traits>
  16. #include <variant>
  17. #include "test_macros.h"
  18. #include "test_workarounds.h"
  19. struct NonT {
  20. NonT(int v) : value(v) {}
  21. NonT(const NonT &o) : value(o.value) {}
  22. int value;
  23. };
  24. static_assert(!std::is_trivially_copy_constructible<NonT>::value, "");
  25. struct NoCopy {
  26. NoCopy(const NoCopy &) = delete;
  27. };
  28. struct MoveOnly {
  29. MoveOnly(const MoveOnly &) = delete;
  30. MoveOnly(MoveOnly &&) = default;
  31. };
  32. struct MoveOnlyNT {
  33. MoveOnlyNT(const MoveOnlyNT &) = delete;
  34. MoveOnlyNT(MoveOnlyNT &&) {}
  35. };
  36. struct NTCopy {
  37. constexpr NTCopy(int v) : value(v) {}
  38. NTCopy(const NTCopy &that) : value(that.value) {}
  39. NTCopy(NTCopy &&) = delete;
  40. int value;
  41. };
  42. static_assert(!std::is_trivially_copy_constructible<NTCopy>::value, "");
  43. static_assert(std::is_copy_constructible<NTCopy>::value, "");
  44. struct TCopy {
  45. constexpr TCopy(int v) : value(v) {}
  46. TCopy(TCopy const &) = default;
  47. TCopy(TCopy &&) = delete;
  48. int value;
  49. };
  50. static_assert(std::is_trivially_copy_constructible<TCopy>::value, "");
  51. struct TCopyNTMove {
  52. constexpr TCopyNTMove(int v) : value(v) {}
  53. TCopyNTMove(const TCopyNTMove&) = default;
  54. TCopyNTMove(TCopyNTMove&& that) : value(that.value) { that.value = -1; }
  55. int value;
  56. };
  57. static_assert(std::is_trivially_copy_constructible<TCopyNTMove>::value, "");
  58. #ifndef TEST_HAS_NO_EXCEPTIONS
  59. struct MakeEmptyT {
  60. static int alive;
  61. MakeEmptyT() { ++alive; }
  62. MakeEmptyT(const MakeEmptyT &) {
  63. ++alive;
  64. // Don't throw from the copy constructor since variant's assignment
  65. // operator performs a copy before committing to the assignment.
  66. }
  67. MakeEmptyT(MakeEmptyT &&) { throw 42; }
  68. MakeEmptyT &operator=(const MakeEmptyT &) { throw 42; }
  69. MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
  70. ~MakeEmptyT() { --alive; }
  71. };
  72. int MakeEmptyT::alive = 0;
  73. template <class Variant> void makeEmpty(Variant &v) {
  74. Variant v2(std::in_place_type<MakeEmptyT>);
  75. try {
  76. v = std::move(v2);
  77. assert(false);
  78. } catch (...) {
  79. assert(v.valueless_by_exception());
  80. }
  81. }
  82. #endif // TEST_HAS_NO_EXCEPTIONS
  83. void test_copy_ctor_sfinae() {
  84. {
  85. using V = std::variant<int, long>;
  86. static_assert(std::is_copy_constructible<V>::value, "");
  87. }
  88. {
  89. using V = std::variant<int, NoCopy>;
  90. static_assert(!std::is_copy_constructible<V>::value, "");
  91. }
  92. {
  93. using V = std::variant<int, MoveOnly>;
  94. static_assert(!std::is_copy_constructible<V>::value, "");
  95. }
  96. {
  97. using V = std::variant<int, MoveOnlyNT>;
  98. static_assert(!std::is_copy_constructible<V>::value, "");
  99. }
  100. // Make sure we properly propagate triviality (see P0602R4).
  101. #if TEST_STD_VER > 17
  102. {
  103. using V = std::variant<int, long>;
  104. static_assert(std::is_trivially_copy_constructible<V>::value, "");
  105. }
  106. {
  107. using V = std::variant<int, NTCopy>;
  108. static_assert(!std::is_trivially_copy_constructible<V>::value, "");
  109. static_assert(std::is_copy_constructible<V>::value, "");
  110. }
  111. {
  112. using V = std::variant<int, TCopy>;
  113. static_assert(std::is_trivially_copy_constructible<V>::value, "");
  114. }
  115. {
  116. using V = std::variant<int, TCopyNTMove>;
  117. static_assert(std::is_trivially_copy_constructible<V>::value, "");
  118. }
  119. #endif // > C++17
  120. }
  121. void test_copy_ctor_basic() {
  122. {
  123. std::variant<int> v(std::in_place_index<0>, 42);
  124. std::variant<int> v2 = v;
  125. assert(v2.index() == 0);
  126. assert(std::get<0>(v2) == 42);
  127. }
  128. {
  129. std::variant<int, long> v(std::in_place_index<1>, 42);
  130. std::variant<int, long> v2 = v;
  131. assert(v2.index() == 1);
  132. assert(std::get<1>(v2) == 42);
  133. }
  134. {
  135. std::variant<NonT> v(std::in_place_index<0>, 42);
  136. assert(v.index() == 0);
  137. std::variant<NonT> v2(v);
  138. assert(v2.index() == 0);
  139. assert(std::get<0>(v2).value == 42);
  140. }
  141. {
  142. std::variant<int, NonT> v(std::in_place_index<1>, 42);
  143. assert(v.index() == 1);
  144. std::variant<int, NonT> v2(v);
  145. assert(v2.index() == 1);
  146. assert(std::get<1>(v2).value == 42);
  147. }
  148. // Make sure we properly propagate triviality, which implies constexpr-ness (see P0602R4).
  149. #if TEST_STD_VER > 17
  150. {
  151. constexpr std::variant<int> v(std::in_place_index<0>, 42);
  152. static_assert(v.index() == 0, "");
  153. constexpr std::variant<int> v2 = v;
  154. static_assert(v2.index() == 0, "");
  155. static_assert(std::get<0>(v2) == 42, "");
  156. }
  157. {
  158. constexpr std::variant<int, long> v(std::in_place_index<1>, 42);
  159. static_assert(v.index() == 1, "");
  160. constexpr std::variant<int, long> v2 = v;
  161. static_assert(v2.index() == 1, "");
  162. static_assert(std::get<1>(v2) == 42, "");
  163. }
  164. {
  165. constexpr std::variant<TCopy> v(std::in_place_index<0>, 42);
  166. static_assert(v.index() == 0, "");
  167. constexpr std::variant<TCopy> v2(v);
  168. static_assert(v2.index() == 0, "");
  169. static_assert(std::get<0>(v2).value == 42, "");
  170. }
  171. {
  172. constexpr std::variant<int, TCopy> v(std::in_place_index<1>, 42);
  173. static_assert(v.index() == 1, "");
  174. constexpr std::variant<int, TCopy> v2(v);
  175. static_assert(v2.index() == 1, "");
  176. static_assert(std::get<1>(v2).value == 42, "");
  177. }
  178. {
  179. constexpr std::variant<TCopyNTMove> v(std::in_place_index<0>, 42);
  180. static_assert(v.index() == 0, "");
  181. constexpr std::variant<TCopyNTMove> v2(v);
  182. static_assert(v2.index() == 0, "");
  183. static_assert(std::get<0>(v2).value == 42, "");
  184. }
  185. {
  186. constexpr std::variant<int, TCopyNTMove> v(std::in_place_index<1>, 42);
  187. static_assert(v.index() == 1, "");
  188. constexpr std::variant<int, TCopyNTMove> v2(v);
  189. static_assert(v2.index() == 1, "");
  190. static_assert(std::get<1>(v2).value == 42, "");
  191. }
  192. #endif // > C++17
  193. }
  194. void test_copy_ctor_valueless_by_exception() {
  195. #ifndef TEST_HAS_NO_EXCEPTIONS
  196. using V = std::variant<int, MakeEmptyT>;
  197. V v1;
  198. makeEmpty(v1);
  199. const V &cv1 = v1;
  200. V v(cv1);
  201. assert(v.valueless_by_exception());
  202. #endif // TEST_HAS_NO_EXCEPTIONS
  203. }
  204. template <size_t Idx>
  205. constexpr bool test_constexpr_copy_ctor_imp(std::variant<long, void*, const int> const& v) {
  206. auto v2 = v;
  207. return v2.index() == v.index() &&
  208. v2.index() == Idx &&
  209. std::get<Idx>(v2) == std::get<Idx>(v);
  210. }
  211. void test_constexpr_copy_ctor() {
  212. // Make sure we properly propagate triviality, which implies constexpr-ness (see P0602R4).
  213. #if TEST_STD_VER > 17
  214. using V = std::variant<long, void*, const int>;
  215. #ifdef TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE
  216. static_assert(std::is_trivially_destructible<V>::value, "");
  217. static_assert(std::is_trivially_copy_constructible<V>::value, "");
  218. static_assert(std::is_trivially_move_constructible<V>::value, "");
  219. static_assert(!std::is_copy_assignable<V>::value, "");
  220. static_assert(!std::is_move_assignable<V>::value, "");
  221. #else // TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE
  222. static_assert(std::is_trivially_copyable<V>::value, "");
  223. #endif // TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE
  224. static_assert(test_constexpr_copy_ctor_imp<0>(V(42l)), "");
  225. static_assert(test_constexpr_copy_ctor_imp<1>(V(nullptr)), "");
  226. static_assert(test_constexpr_copy_ctor_imp<2>(V(101)), "");
  227. #endif // > C++17
  228. }
  229. int main(int, char**) {
  230. test_copy_ctor_basic();
  231. test_copy_ctor_valueless_by_exception();
  232. test_copy_ctor_sfinae();
  233. test_constexpr_copy_ctor();
  234. #if 0
  235. // disable this for the moment; it fails on older compilers.
  236. // Need to figure out which compilers will support it.
  237. { // This is the motivating example from P0739R0
  238. std::variant<int, double> v1(3);
  239. std::variant v2 = v1;
  240. (void) v2;
  241. }
  242. #endif
  243. return 0;
  244. }