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