emplace.pass.cpp (9037B)
1 //===----------------------------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // UNSUPPORTED: c++98, c++03, c++11, c++14 11 12 // XFAIL: availability=macosx10.13 13 // XFAIL: availability=macosx10.12 14 // XFAIL: availability=macosx10.11 15 // XFAIL: availability=macosx10.10 16 // XFAIL: availability=macosx10.9 17 // XFAIL: availability=macosx10.8 18 // XFAIL: availability=macosx10.7 19 20 // <any> 21 22 // template <class T, class ...Args> T& emplace(Args&&...); 23 // template <class T, class U, class ...Args> 24 // T& emplace(initializer_list<U>, Args&&...); 25 26 #include <any> 27 #include <cassert> 28 29 #include "any_helpers.h" 30 #include "count_new.hpp" 31 #include "test_macros.h" 32 33 using std::any; 34 using std::any_cast; 35 36 struct Tracked { 37 static int count; 38 Tracked() {++count;} 39 ~Tracked() { --count; } 40 }; 41 int Tracked::count = 0; 42 43 template <class Type> 44 void test_emplace_type() { 45 // constructing from a small type should perform no allocations. 46 DisableAllocationGuard g(isSmallType<Type>()); ((void)g); 47 assert(Type::count == 0); 48 Type::reset(); 49 { 50 any a(std::in_place_type<Tracked>); 51 assert(Tracked::count == 1); 52 53 auto &v = a.emplace<Type>(); 54 static_assert( std::is_same_v<Type&, decltype(v)>, "" ); 55 assert(&v == std::any_cast<Type>(&a)); 56 57 assert(Tracked::count == 0); 58 assert(Type::count == 1); 59 assert(Type::copied == 0); 60 assert(Type::moved == 0); 61 assertContains<Type>(a, 0); 62 } 63 assert(Type::count == 0); 64 Type::reset(); 65 { 66 any a(std::in_place_type<Tracked>); 67 assert(Tracked::count == 1); 68 69 auto &v = a.emplace<Type>(101); 70 static_assert( std::is_same_v<Type&, decltype(v)>, "" ); 71 assert(&v == std::any_cast<Type>(&a)); 72 73 assert(Tracked::count == 0); 74 assert(Type::count == 1); 75 assert(Type::copied == 0); 76 assert(Type::moved == 0); 77 assertContains<Type>(a, 101); 78 } 79 assert(Type::count == 0); 80 Type::reset(); 81 { 82 any a(std::in_place_type<Tracked>); 83 assert(Tracked::count == 1); 84 85 auto &v = a.emplace<Type>(-1, 42, -1); 86 static_assert( std::is_same_v<Type&, decltype(v)>, "" ); 87 assert(&v == std::any_cast<Type>(&a)); 88 89 assert(Tracked::count == 0); 90 assert(Type::count == 1); 91 assert(Type::copied == 0); 92 assert(Type::moved == 0); 93 assertContains<Type>(a, 42); 94 } 95 assert(Type::count == 0); 96 Type::reset(); 97 } 98 99 template <class Type> 100 void test_emplace_type_tracked() { 101 // constructing from a small type should perform no allocations. 102 DisableAllocationGuard g(isSmallType<Type>()); ((void)g); 103 { 104 any a(std::in_place_type<Tracked>); 105 assert(Tracked::count == 1); 106 auto &v = a.emplace<Type>(); 107 static_assert( std::is_same_v<Type&, decltype(v)>, "" ); 108 assert(&v == std::any_cast<Type>(&a)); 109 110 assert(Tracked::count == 0); 111 assertArgsMatch<Type>(a); 112 } 113 { 114 any a(std::in_place_type<Tracked>); 115 assert(Tracked::count == 1); 116 auto &v = a.emplace<Type>(-1, 42, -1); 117 static_assert( std::is_same_v<Type&, decltype(v)>, "" ); 118 assert(&v == std::any_cast<Type>(&a)); 119 120 assert(Tracked::count == 0); 121 assertArgsMatch<Type, int, int, int>(a); 122 } 123 // initializer_list constructor tests 124 { 125 any a(std::in_place_type<Tracked>); 126 assert(Tracked::count == 1); 127 auto &v = a.emplace<Type>({-1, 42, -1}); 128 static_assert( std::is_same_v<Type&, decltype(v)>, "" ); 129 assert(&v == std::any_cast<Type>(&a)); 130 131 assert(Tracked::count == 0); 132 assertArgsMatch<Type, std::initializer_list<int>>(a); 133 } 134 { 135 int x = 42; 136 any a(std::in_place_type<Tracked>); 137 assert(Tracked::count == 1); 138 auto &v = a.emplace<Type>({-1, 42, -1}, x); 139 static_assert( std::is_same_v<Type&, decltype(v)>, "" ); 140 assert(&v == std::any_cast<Type>(&a)); 141 142 assert(Tracked::count == 0); 143 assertArgsMatch<Type, std::initializer_list<int>, int&>(a); 144 } 145 } 146 147 #ifndef TEST_HAS_NO_EXCEPTIONS 148 149 struct SmallThrows { 150 SmallThrows(int) { throw 42; } 151 SmallThrows(std::initializer_list<int>, int) { throw 42; } 152 }; 153 static_assert(IsSmallObject<SmallThrows>::value, ""); 154 155 struct LargeThrows { 156 LargeThrows(int) { throw 42; } 157 LargeThrows(std::initializer_list<int>, int) { throw 42; } 158 int data[sizeof(std::any)]; 159 }; 160 static_assert(!IsSmallObject<LargeThrows>::value, ""); 161 162 template <class Type> 163 void test_emplace_throws() 164 { 165 // any stores small type 166 { 167 std::any a(small{42}); 168 assert(small::count == 1); 169 try { 170 auto &v = a.emplace<Type>(101); 171 static_assert( std::is_same_v<Type&, decltype(v)>, "" ); 172 assert(false); 173 } catch (int const&) { 174 } 175 assert(small::count == 0); 176 } 177 { 178 std::any a(small{42}); 179 assert(small::count == 1); 180 try { 181 auto &v = a.emplace<Type>({1, 2, 3}, 101); 182 static_assert( std::is_same_v<Type&, decltype(v)>, "" ); 183 assert(false); 184 } catch (int const&) { 185 } 186 assert(small::count == 0); 187 } 188 // any stores large type 189 { 190 std::any a(large{42}); 191 assert(large::count == 1); 192 try { 193 auto &v = a.emplace<Type>(101); 194 static_assert( std::is_same_v<Type&, decltype(v)>, "" ); 195 assert(false); 196 } catch (int const&) { 197 } 198 assert(large::count == 0); 199 } 200 { 201 std::any a(large{42}); 202 assert(large::count == 1); 203 try { 204 auto &v = a.emplace<Type>({1, 2, 3}, 101); 205 static_assert( std::is_same_v<Type&, decltype(v)>, "" ); 206 assert(false); 207 } catch (int const&) { 208 } 209 assert(large::count == 0); 210 } 211 } 212 213 #endif 214 215 template <class T, class ...Args> 216 constexpr auto has_emplace(int) 217 -> decltype(std::any{}.emplace<T>(std::declval<Args>()...), true) { return true; } 218 219 template <class ...Args> 220 constexpr bool has_emplace(long) { return false; } 221 222 template <class ...Args> 223 constexpr bool has_emplace() { return has_emplace<Args...>(0); } 224 225 226 template <class T, class IT, class ...Args> 227 constexpr auto has_emplace_init_list(int) 228 -> decltype(std::any{}.emplace<T>( 229 {std::declval<IT>(), std::declval<IT>(), std::declval<IT>()}, 230 std::declval<Args>()...), true) { return true; } 231 232 template <class ...Args> 233 constexpr bool has_emplace_init_list(long) { return false; } 234 235 template <class ...Args> 236 constexpr bool has_emplace_init_list() { return has_emplace_init_list<Args...>(0); } 237 238 239 void test_emplace_sfinae_constraints() { 240 { 241 static_assert(has_emplace<int>(), ""); 242 static_assert(has_emplace<int, int>(), ""); 243 static_assert(!has_emplace<int, int, int>(), "not constructible"); 244 static_assert(!has_emplace_init_list<int, int>(), "not constructible from il"); 245 } 246 { 247 static_assert(has_emplace<small>(), ""); 248 static_assert(has_emplace<large>(), ""); 249 static_assert(!has_emplace<small, void*>(), ""); 250 static_assert(!has_emplace<large, void*>(), ""); 251 252 static_assert(has_emplace_init_list<small, int>(), ""); 253 static_assert(has_emplace_init_list<large, int>(), ""); 254 static_assert(!has_emplace_init_list<small, void*>(), ""); 255 static_assert(!has_emplace_init_list<large, void*>(), ""); 256 } 257 { 258 // Test that the emplace SFINAE's away when the 259 // argument is non-copyable 260 struct NoCopy { 261 NoCopy() = default; 262 NoCopy(NoCopy const&) = delete; 263 NoCopy(int) {} 264 NoCopy(std::initializer_list<int>, int, int) {} 265 }; 266 static_assert(!has_emplace<NoCopy>(), ""); 267 static_assert(!has_emplace<NoCopy, int>(), ""); 268 static_assert(!has_emplace_init_list<NoCopy, int, int, int>(), ""); 269 static_assert(!has_emplace<NoCopy&>(), ""); 270 static_assert(!has_emplace<NoCopy&, int>(), ""); 271 static_assert(!has_emplace_init_list<NoCopy&, int, int, int>(), ""); 272 static_assert(!has_emplace<NoCopy&&>(), ""); 273 static_assert(!has_emplace<NoCopy&&, int>(), ""); 274 static_assert(!has_emplace_init_list<NoCopy&&, int, int, int>(), ""); 275 276 } 277 } 278 279 int main() { 280 test_emplace_type<small>(); 281 test_emplace_type<large>(); 282 test_emplace_type<small_throws_on_copy>(); 283 test_emplace_type<large_throws_on_copy>(); 284 test_emplace_type<throws_on_move>(); 285 test_emplace_type_tracked<small_tracked_t>(); 286 test_emplace_type_tracked<large_tracked_t>(); 287 test_emplace_sfinae_constraints(); 288 #ifndef TEST_HAS_NO_EXCEPTIONS 289 test_emplace_throws<SmallThrows>(); 290 test_emplace_throws<LargeThrows>(); 291 #endif 292 }