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