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