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