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