T.pass.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  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 && !libcpp-no-exceptions
  11. // <variant>
  12. // template <class ...Types> class variant;
  13. // template <class T> constexpr variant(T&&) noexcept(see below);
  14. #include <cassert>
  15. #include <string>
  16. #include <type_traits>
  17. #include <variant>
  18. #include <memory>
  19. #include "test_macros.h"
  20. #include "variant_test_helpers.h"
  21. struct Dummy {
  22. Dummy() = default;
  23. };
  24. struct ThrowsT {
  25. ThrowsT(int) noexcept(false) {}
  26. };
  27. struct NoThrowT {
  28. NoThrowT(int) noexcept(true) {}
  29. };
  30. struct AnyConstructible { template <typename T> AnyConstructible(T&&) {} };
  31. struct NoConstructible { NoConstructible() = delete; };
  32. template <class T>
  33. struct RValueConvertibleFrom { RValueConvertibleFrom(T&&) {} };
  34. void test_T_ctor_noexcept() {
  35. {
  36. using V = std::variant<Dummy, NoThrowT>;
  37. static_assert(std::is_nothrow_constructible<V, int>::value, "");
  38. }
  39. {
  40. using V = std::variant<Dummy, ThrowsT>;
  41. static_assert(!std::is_nothrow_constructible<V, int>::value, "");
  42. }
  43. }
  44. void test_T_ctor_sfinae() {
  45. {
  46. using V = std::variant<long, long long>;
  47. static_assert(!std::is_constructible<V, int>::value, "ambiguous");
  48. }
  49. {
  50. using V = std::variant<std::string, std::string>;
  51. static_assert(!std::is_constructible<V, const char *>::value, "ambiguous");
  52. }
  53. {
  54. using V = std::variant<std::string, void *>;
  55. static_assert(!std::is_constructible<V, int>::value,
  56. "no matching constructor");
  57. }
  58. {
  59. using V = std::variant<std::string, float>;
  60. static_assert(std::is_constructible<V, int>::value == VariantAllowsNarrowingConversions,
  61. "no matching constructor");
  62. }
  63. {
  64. using V = std::variant<std::unique_ptr<int>, bool>;
  65. static_assert(!std::is_constructible<V, std::unique_ptr<char>>::value,
  66. "no explicit bool in constructor");
  67. struct X {
  68. operator void*();
  69. };
  70. static_assert(!std::is_constructible<V, X>::value,
  71. "no boolean conversion in constructor");
  72. static_assert(!std::is_constructible<V, std::false_type>::value,
  73. "no converted to bool in constructor");
  74. }
  75. {
  76. struct X {};
  77. struct Y {
  78. operator X();
  79. };
  80. using V = std::variant<X>;
  81. static_assert(std::is_constructible<V, Y>::value,
  82. "regression on user-defined conversions in constructor");
  83. }
  84. {
  85. using V = std::variant<AnyConstructible, NoConstructible>;
  86. static_assert(
  87. !std::is_constructible<V, std::in_place_type_t<NoConstructible>>::value,
  88. "no matching constructor");
  89. static_assert(!std::is_constructible<V, std::in_place_index_t<1>>::value,
  90. "no matching constructor");
  91. }
  92. #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
  93. {
  94. using V = std::variant<int, int &&>;
  95. static_assert(!std::is_constructible<V, int>::value, "ambiguous");
  96. }
  97. {
  98. using V = std::variant<int, const int &>;
  99. static_assert(!std::is_constructible<V, int>::value, "ambiguous");
  100. }
  101. #endif
  102. }
  103. void test_T_ctor_basic() {
  104. {
  105. constexpr std::variant<int> v(42);
  106. static_assert(v.index() == 0, "");
  107. static_assert(std::get<0>(v) == 42, "");
  108. }
  109. {
  110. constexpr std::variant<int, long> v(42l);
  111. static_assert(v.index() == 1, "");
  112. static_assert(std::get<1>(v) == 42, "");
  113. }
  114. #ifndef TEST_VARIANT_ALLOWS_NARROWING_CONVERSIONS
  115. {
  116. constexpr std::variant<unsigned, long> v(42);
  117. static_assert(v.index() == 1, "");
  118. static_assert(std::get<1>(v) == 42, "");
  119. }
  120. #endif
  121. {
  122. std::variant<std::string, bool const> v = "foo";
  123. assert(v.index() == 0);
  124. assert(std::get<0>(v) == "foo");
  125. }
  126. {
  127. std::variant<bool volatile, std::unique_ptr<int>> v = nullptr;
  128. assert(v.index() == 1);
  129. assert(std::get<1>(v) == nullptr);
  130. }
  131. {
  132. std::variant<bool volatile const, int> v = true;
  133. assert(v.index() == 0);
  134. assert(std::get<0>(v));
  135. }
  136. {
  137. std::variant<RValueConvertibleFrom<int>> v1 = 42;
  138. assert(v1.index() == 0);
  139. int x = 42;
  140. std::variant<RValueConvertibleFrom<int>, AnyConstructible> v2 = x;
  141. assert(v2.index() == 1);
  142. }
  143. #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
  144. {
  145. using V = std::variant<const int &, int &&, long>;
  146. static_assert(std::is_convertible<int &, V>::value, "must be implicit");
  147. int x = 42;
  148. V v(x);
  149. assert(v.index() == 0);
  150. assert(&std::get<0>(v) == &x);
  151. }
  152. {
  153. using V = std::variant<const int &, int &&, long>;
  154. static_assert(std::is_convertible<int, V>::value, "must be implicit");
  155. int x = 42;
  156. V v(std::move(x));
  157. assert(v.index() == 1);
  158. assert(&std::get<1>(v) == &x);
  159. }
  160. #endif
  161. }
  162. struct BoomOnAnything {
  163. template <class T>
  164. constexpr BoomOnAnything(T) { static_assert(!std::is_same<T, T>::value, ""); }
  165. };
  166. void test_no_narrowing_check_for_class_types() {
  167. using V = std::variant<int, BoomOnAnything>;
  168. V v(42);
  169. assert(v.index() == 0);
  170. assert(std::get<0>(v) == 42);
  171. }
  172. struct Bar {};
  173. struct Baz {};
  174. void test_construction_with_repeated_types() {
  175. using V = std::variant<int, Bar, Baz, int, Baz, int, int>;
  176. static_assert(!std::is_constructible<V, int>::value, "");
  177. static_assert(!std::is_constructible<V, Baz>::value, "");
  178. // OK, the selected type appears only once and so it shouldn't
  179. // be affected by the duplicate types.
  180. static_assert(std::is_constructible<V, Bar>::value, "");
  181. }
  182. int main(int, char**) {
  183. test_T_ctor_basic();
  184. test_T_ctor_noexcept();
  185. test_T_ctor_sfinae();
  186. test_no_narrowing_check_for_class_types();
  187. test_construction_with_repeated_types();
  188. return 0;
  189. }