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++98, c++03, c++11, c++14 11 12 // XFAIL: dylib-has-no-bad_variant_access && !libcpp-no-exceptions 13 14 // <variant> 15 16 // template <class ...Types> class variant; 17 18 // template <size_t I, class ...Args> 19 // variant_alternative_t<I, variant<Types...>>& emplace(Args&&... args); 20 21 #include <cassert> 22 #include <string> 23 #include <type_traits> 24 #include <variant> 25 26 #include "archetypes.h" 27 #include "test_convertible.h" 28 #include "test_macros.h" 29 #include "variant_test_helpers.h" 30 31 template <class Var, size_t I, class... Args> 32 constexpr auto test_emplace_exists_imp(int) -> decltype( 33 std::declval<Var>().template emplace<I>(std::declval<Args>()...), true) { 34 return true; 35 } 36 37 template <class, size_t, class...> 38 constexpr auto test_emplace_exists_imp(long) -> bool { 39 return false; 40 } 41 42 template <class Var, size_t I, class... Args> constexpr bool emplace_exists() { 43 return test_emplace_exists_imp<Var, I, Args...>(0); 44 } 45 46 void test_emplace_sfinae() { 47 { 48 using V = std::variant<int, void *, const void *, TestTypes::NoCtors>; 49 static_assert(emplace_exists<V, 0>(), ""); 50 static_assert(emplace_exists<V, 0, int>(), ""); 51 static_assert(!emplace_exists<V, 0, decltype(nullptr)>(), 52 "cannot construct"); 53 static_assert(emplace_exists<V, 1, decltype(nullptr)>(), ""); 54 static_assert(emplace_exists<V, 1, int *>(), ""); 55 static_assert(!emplace_exists<V, 1, const int *>(), ""); 56 static_assert(!emplace_exists<V, 1, int>(), "cannot construct"); 57 static_assert(emplace_exists<V, 2, const int *>(), ""); 58 static_assert(emplace_exists<V, 2, int *>(), ""); 59 static_assert(!emplace_exists<V, 3>(), "cannot construct"); 60 } 61 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES) 62 { 63 using V = std::variant<int, int &, const int &, int &&, TestTypes::NoCtors>; 64 static_assert(emplace_exists<V, 0>(), ""); 65 static_assert(emplace_exists<V, 0, int>(), ""); 66 static_assert(emplace_exists<V, 0, long long>(), ""); 67 static_assert(!emplace_exists<V, 0, int, int>(), "too many args"); 68 static_assert(emplace_exists<V, 1, int &>(), ""); 69 static_assert(!emplace_exists<V, 1>(), "cannot default construct ref"); 70 static_assert(!emplace_exists<V, 1, const int &>(), "cannot bind ref"); 71 static_assert(!emplace_exists<V, 1, int &&>(), "cannot bind ref"); 72 static_assert(emplace_exists<V, 2, int &>(), ""); 73 static_assert(emplace_exists<V, 2, const int &>(), ""); 74 static_assert(emplace_exists<V, 2, int &&>(), ""); 75 static_assert(!emplace_exists<V, 2, void *>(), 76 "not constructible from void*"); 77 static_assert(emplace_exists<V, 3, int>(), ""); 78 static_assert(!emplace_exists<V, 3, int &>(), "cannot bind ref"); 79 static_assert(!emplace_exists<V, 3, const int &>(), "cannot bind ref"); 80 static_assert(!emplace_exists<V, 3, const int &&>(), "cannot bind ref"); 81 static_assert(!emplace_exists<V, 4>(), "no ctors"); 82 } 83 #endif 84 } 85 86 void test_basic() { 87 { 88 using V = std::variant<int>; 89 V v(42); 90 auto& ref1 = v.emplace<0>(); 91 static_assert(std::is_same_v<int&, decltype(ref1)>, ""); 92 assert(std::get<0>(v) == 0); 93 assert(&ref1 == &std::get<0>(v)); 94 auto& ref2 = v.emplace<0>(42); 95 static_assert(std::is_same_v<int&, decltype(ref2)>, ""); 96 assert(std::get<0>(v) == 42); 97 assert(&ref2 == &std::get<0>(v)); 98 } 99 { 100 using V = 101 std::variant<int, long, const void *, TestTypes::NoCtors, std::string>; 102 const int x = 100; 103 V v(std::in_place_index<0>, -1); 104 // default emplace a value 105 auto& ref1 = v.emplace<1>(); 106 static_assert(std::is_same_v<long&, decltype(ref1)>, ""); 107 assert(std::get<1>(v) == 0); 108 assert(&ref1 == &std::get<1>(v)); 109 auto& ref2 = v.emplace<2>(&x); 110 static_assert(std::is_same_v<const void*&, decltype(ref2)>, ""); 111 assert(std::get<2>(v) == &x); 112 assert(&ref2 == &std::get<2>(v)); 113 // emplace with multiple args 114 auto& ref3 = v.emplace<4>(3u, 'a'); 115 static_assert(std::is_same_v<std::string&, decltype(ref3)>, ""); 116 assert(std::get<4>(v) == "aaa"); 117 assert(&ref3 == &std::get<4>(v)); 118 } 119 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES) 120 { 121 using V = std::variant<int, long, const int &, int &&, TestTypes::NoCtors, 122 std::string>; 123 const int x = 100; 124 int y = 42; 125 int z = 43; 126 V v(std::in_place_index<0>, -1); 127 // default emplace a value 128 auto& ref1 = v.emplace<1>(); 129 static_assert(std::is_same_v<long&, decltype(ref1)>, ""); 130 assert(std::get<1>(v) == 0); 131 assert(&ref1 == &std::get<1>(v)); 132 // emplace a reference 133 auto& ref2 = v.emplace<2>(x); 134 static_assert(std::is_same_v<&, decltype(ref)>, ""); 135 assert(&std::get<2>(v) == &x); 136 assert(&ref2 == &std::get<2>(v)); 137 // emplace an rvalue reference 138 auto& ref3 = v.emplace<3>(std::move(y)); 139 static_assert(std::is_same_v<&, decltype(ref)>, ""); 140 assert(&std::get<3>(v) == &y); 141 assert(&ref3 == &std::get<3>(v)); 142 // re-emplace a new reference over the active member 143 auto& ref4 = v.emplace<3>(std::move(z)); 144 static_assert(std::is_same_v<&, decltype(ref)>, ""); 145 assert(&std::get<3>(v) == &z); 146 assert(&ref4 == &std::get<3>(v)); 147 // emplace with multiple args 148 auto& ref5 = v.emplace<5>(3u, 'a'); 149 static_assert(std::is_same_v<std::string&, decltype(ref5)>, ""); 150 assert(std::get<5>(v) == "aaa"); 151 assert(&ref5 == &std::get<5>(v)); 152 } 153 #endif 154 } 155 156 int main(int, char**) { 157 test_basic(); 158 test_emplace_sfinae(); 159 160 return 0; 161 } 162