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 // <variant> 14 15 // template <class ...Types> class variant; 16 17 // variant(variant const&); 18 19 #include <cassert> 20 #include <type_traits> 21 #include <variant> 22 23 #include "test_macros.h" 24 25 struct NonT { 26 NonT(int v) : value(v) {} 27 NonT(const NonT &o) : value(o.value) {} 28 int value; 29 }; 30 static_assert(!std::is_trivially_copy_constructible<NonT>::value, ""); 31 32 struct NoCopy { 33 NoCopy(const NoCopy &) = delete; 34 }; 35 36 struct MoveOnly { 37 MoveOnly(const MoveOnly &) = delete; 38 MoveOnly(MoveOnly &&) = default; 39 }; 40 41 struct MoveOnlyNT { 42 MoveOnlyNT(const MoveOnlyNT &) = delete; 43 MoveOnlyNT(MoveOnlyNT &&) {} 44 }; 45 46 #ifndef TEST_HAS_NO_EXCEPTIONS 47 struct MakeEmptyT { 48 static int alive; 49 MakeEmptyT() { ++alive; } 50 MakeEmptyT(const MakeEmptyT &) { 51 ++alive; 52 // Don't throw from the copy constructor since variant's assignment 53 // operator performs a copy before committing to the assignment. 54 } 55 MakeEmptyT(MakeEmptyT &&) { throw 42; } 56 MakeEmptyT &operator=(const MakeEmptyT &) { throw 42; } 57 MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; } 58 ~MakeEmptyT() { --alive; } 59 }; 60 61 int MakeEmptyT::alive = 0; 62 63 template <class Variant> void makeEmpty(Variant &v) { 64 Variant v2(std::in_place_type<MakeEmptyT>); 65 try { 66 v = v2; 67 assert(false); 68 } catch (...) { 69 assert(v.valueless_by_exception()); 70 } 71 } 72 #endif // TEST_HAS_NO_EXCEPTIONS 73 74 void test_copy_ctor_sfinae() { 75 { 76 using V = std::variant<int, long>; 77 static_assert(std::is_copy_constructible<V>::value, ""); 78 } 79 { 80 using V = std::variant<int, NoCopy>; 81 static_assert(!std::is_copy_constructible<V>::value, ""); 82 } 83 { 84 using V = std::variant<int, MoveOnly>; 85 static_assert(!std::is_copy_constructible<V>::value, ""); 86 } 87 { 88 using V = std::variant<int, MoveOnlyNT>; 89 static_assert(!std::is_copy_constructible<V>::value, ""); 90 } 91 } 92 93 void test_copy_ctor_basic() { 94 { 95 std::variant<int> v(std::in_place_index<0>, 42); 96 std::variant<int> v2 = v; 97 assert(v2.index() == 0); 98 assert(std::get<0>(v2) == 42); 99 } 100 { 101 std::variant<int, long> v(std::in_place_index<1>, 42); 102 std::variant<int, long> v2 = v; 103 assert(v2.index() == 1); 104 assert(std::get<1>(v2) == 42); 105 } 106 { 107 std::variant<NonT> v(std::in_place_index<0>, 42); 108 assert(v.index() == 0); 109 std::variant<NonT> v2(v); 110 assert(v2.index() == 0); 111 assert(std::get<0>(v2).value == 42); 112 } 113 { 114 std::variant<int, NonT> v(std::in_place_index<1>, 42); 115 assert(v.index() == 1); 116 std::variant<int, NonT> v2(v); 117 assert(v2.index() == 1); 118 assert(std::get<1>(v2).value == 42); 119 } 120 } 121 122 void test_copy_ctor_valueless_by_exception() { 123 #ifndef TEST_HAS_NO_EXCEPTIONS 124 using V = std::variant<int, MakeEmptyT>; 125 V v1; 126 makeEmpty(v1); 127 const V &cv1 = v1; 128 V v(cv1); 129 assert(v.valueless_by_exception()); 130 #endif 131 } 132 133 template <size_t Idx> 134 constexpr bool test_constexpr_copy_ctor_extension_imp( 135 std::variant<long, void*, const int> const& v) 136 { 137 auto v2 = v; 138 return v2.index() == v.index() && 139 v2.index() == Idx && 140 std::get<Idx>(v2) == std::get<Idx>(v); 141 } 142 143 void test_constexpr_copy_ctor_extension() { 144 #ifdef _LIBCPP_VERSION 145 using V = std::variant<long, void*, const int>; 146 static_assert(std::is_trivially_copyable<V>::value, ""); 147 static_assert(std::is_trivially_copy_constructible<V>::value, ""); 148 static_assert(test_constexpr_copy_ctor_extension_imp<0>(V(42l)), ""); 149 static_assert(test_constexpr_copy_ctor_extension_imp<1>(V(nullptr)), ""); 150 static_assert(test_constexpr_copy_ctor_extension_imp<2>(V(101)), ""); 151 #endif 152 } 153 154 int main() { 155 test_copy_ctor_basic(); 156 test_copy_ctor_valueless_by_exception(); 157 test_copy_ctor_sfinae(); 158 test_constexpr_copy_ctor_extension(); 159 } 160