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