any_cast_reference.pass.cpp (10808B)
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 ValueType> 23 // ValueType const any_cast(any const&); 24 // 25 // template <class ValueType> 26 // ValueType any_cast(any &); 27 // 28 // template <class ValueType> 29 // ValueType any_cast(any &&); 30 31 #include <any> 32 #include <type_traits> 33 #include <cassert> 34 35 #include "any_helpers.h" 36 #include "count_new.hpp" 37 #include "test_macros.h" 38 39 using std::any; 40 using std::any_cast; 41 using std::bad_any_cast; 42 43 44 // Test that the operators are NOT marked noexcept. 45 void test_cast_is_not_noexcept() { 46 any a; 47 static_assert(!noexcept(any_cast<int>(static_cast<any&>(a))), ""); 48 static_assert(!noexcept(any_cast<int>(static_cast<any const&>(a))), ""); 49 static_assert(!noexcept(any_cast<int>(static_cast<any &&>(a))), ""); 50 } 51 52 // Test that the return type of any_cast is correct. 53 void test_cast_return_type() { 54 any a; 55 static_assert(std::is_same<decltype(any_cast<int>(a)), int>::value, ""); 56 static_assert(std::is_same<decltype(any_cast<int const>(a)), int>::value, ""); 57 static_assert(std::is_same<decltype(any_cast<int&>(a)), int&>::value, ""); 58 static_assert(std::is_same<decltype(any_cast<int const&>(a)), int const&>::value, ""); 59 60 static_assert(std::is_same<decltype(any_cast<int&&>(a)), int&&>::value, ""); 61 static_assert(std::is_same<decltype(any_cast<int const&&>(a)), int const&&>::value, ""); 62 63 static_assert(std::is_same<decltype(any_cast<int>(std::move(a))), int>::value, ""); 64 static_assert(std::is_same<decltype(any_cast<int const>(std::move(a))), int>::value, ""); 65 static_assert(std::is_same<decltype(any_cast<int&>(std::move(a))), int&>::value, ""); 66 static_assert(std::is_same<decltype(any_cast<int const&>(std::move(a))), int const&>::value, ""); 67 68 static_assert(std::is_same<decltype(any_cast<int&&>(std::move(a))), int&&>::value, ""); 69 static_assert(std::is_same<decltype(any_cast<int const&&>(std::move(a))), int const&&>::value, ""); 70 71 any const& ca = a; 72 static_assert(std::is_same<decltype(any_cast<int>(ca)), int>::value, ""); 73 static_assert(std::is_same<decltype(any_cast<int const>(ca)), int>::value, ""); 74 static_assert(std::is_same<decltype(any_cast<int const&>(ca)), int const&>::value, ""); 75 76 static_assert(std::is_same<decltype(any_cast<int const&&>(ca)), int const&&>::value, ""); 77 } 78 79 template <class Type, class ConstT = Type> 80 void checkThrows(any& a) 81 { 82 #if !defined(TEST_HAS_NO_EXCEPTIONS) 83 try { 84 TEST_IGNORE_NODISCARD any_cast<Type>(a); 85 assert(false); 86 } catch (bad_any_cast const &) { 87 // do nothing 88 } catch (...) { 89 assert(false); 90 } 91 92 try { 93 TEST_IGNORE_NODISCARD any_cast<ConstT>(static_cast<any const&>(a)); 94 assert(false); 95 } catch (bad_any_cast const &) { 96 // do nothing 97 } catch (...) { 98 assert(false); 99 } 100 101 try { 102 using RefType = typename std::conditional< 103 std::is_lvalue_reference<Type>::value, 104 typename std::remove_reference<Type>::type&&, 105 Type 106 >::type; 107 TEST_IGNORE_NODISCARD any_cast<RefType>(static_cast<any&&>(a)); 108 assert(false); 109 } catch (bad_any_cast const &) { 110 // do nothing 111 } catch (...) { 112 assert(false); 113 } 114 #else 115 (TEST_IGNORE_NODISCARD a); 116 #endif 117 } 118 119 void test_cast_empty() { 120 // None of these operations should allocate. 121 DisableAllocationGuard g; (TEST_IGNORE_NODISCARD g); 122 any a; 123 checkThrows<int>(a); 124 } 125 126 template <class Type> 127 void test_cast_to_reference() { 128 assert(Type::count == 0); 129 Type::reset(); 130 { 131 any a((Type(42))); 132 any const& ca = a; 133 assert(Type::count == 1); 134 assert(Type::copied == 0); 135 assert(Type::moved == 1); 136 137 // Try a cast to a bad type. 138 // NOTE: Type cannot be an int. 139 checkThrows<int>(a); 140 checkThrows<int&, int const&>(a); 141 checkThrows<Type*, Type const*>(a); 142 checkThrows<Type const*>(a); 143 144 // Check getting a type by reference from a non-const lvalue any. 145 { 146 Type& v = any_cast<Type&>(a); 147 assert(v.value == 42); 148 149 Type const &cv = any_cast<Type const&>(a); 150 assert(&cv == &v); 151 } 152 // Check getting a type by reference from a const lvalue any. 153 { 154 Type const& v = any_cast<Type const&>(ca); 155 assert(v.value == 42); 156 157 Type const &cv = any_cast<Type const&>(ca); 158 assert(&cv == &v); 159 } 160 // Check getting a type by reference from a const rvalue any. 161 { 162 Type const& v = any_cast<Type const&>(std::move(ca)); 163 assert(v.value == 42); 164 165 Type const &cv = any_cast<Type const&>(std::move(ca)); 166 assert(&cv == &v); 167 } 168 // Check getting a type by reference from a const rvalue any. 169 { 170 Type&& v = any_cast<Type&&>(std::move(a)); 171 assert(v.value == 42); 172 assert(any_cast<Type&>(a).value == 42); 173 174 Type&& cv = any_cast<Type&&>(std::move(a)); 175 assert(&cv == &v); 176 assert(any_cast<Type&>(a).value == 42); 177 } 178 // Check getting a type by reference from a const rvalue any. 179 { 180 Type const&& v = any_cast<Type const&&>(std::move(a)); 181 assert(v.value == 42); 182 assert(any_cast<Type&>(a).value == 42); 183 184 Type const&& cv = any_cast<Type const&&>(std::move(a)); 185 assert(&cv == &v); 186 assert(any_cast<Type&>(a).value == 42); 187 } 188 // Check that the original object hasn't been changed. 189 assertContains<Type>(a, 42); 190 191 // Check that no objects have been created/copied/moved. 192 assert(Type::count == 1); 193 assert(Type::copied == 0); 194 assert(Type::moved == 1); 195 } 196 assert(Type::count == 0); 197 } 198 199 template <class Type> 200 void test_cast_to_value() { 201 assert(Type::count == 0); 202 Type::reset(); 203 { 204 any a((Type(42))); 205 assert(Type::count == 1); 206 assert(Type::copied == 0); 207 assert(Type::moved == 1); 208 209 // Try a cast to a bad type. 210 // NOTE: Type cannot be an int. 211 checkThrows<int>(a); 212 checkThrows<int&, int const&>(a); 213 checkThrows<Type*, Type const*>(a); 214 checkThrows<Type const*>(a); 215 216 Type::reset(); // NOTE: reset does not modify Type::count 217 // Check getting Type by value from a non-const lvalue any. 218 // This should cause the non-const copy constructor to be called. 219 { 220 Type t = any_cast<Type>(a); 221 222 assert(Type::count == 2); 223 assert(Type::copied == 1); 224 assert(Type::const_copied == 0); 225 assert(Type::non_const_copied == 1); 226 assert(Type::moved == 0); 227 assert(t.value == 42); 228 } 229 assert(Type::count == 1); 230 Type::reset(); 231 // Check getting const Type by value from a non-const lvalue any. 232 // This should cause the const copy constructor to be called. 233 { 234 Type t = any_cast<Type const>(a); 235 236 assert(Type::count == 2); 237 assert(Type::copied == 1); 238 assert(Type::const_copied == 0); 239 assert(Type::non_const_copied == 1); 240 assert(Type::moved == 0); 241 assert(t.value == 42); 242 } 243 assert(Type::count == 1); 244 Type::reset(); 245 // Check getting Type by value from a non-const lvalue any. 246 // This should cause the const copy constructor to be called. 247 { 248 Type t = any_cast<Type>(static_cast<any const&>(a)); 249 250 assert(Type::count == 2); 251 assert(Type::copied == 1); 252 assert(Type::const_copied == 1); 253 assert(Type::non_const_copied == 0); 254 assert(Type::moved == 0); 255 assert(t.value == 42); 256 } 257 assert(Type::count == 1); 258 Type::reset(); 259 // Check getting Type by value from a non-const rvalue any. 260 // This should cause the non-const copy constructor to be called. 261 { 262 Type t = any_cast<Type>(static_cast<any &&>(a)); 263 264 assert(Type::count == 2); 265 assert(Type::moved == 1); 266 assert(Type::copied == 0); 267 assert(Type::const_copied == 0); 268 assert(Type::non_const_copied == 0); 269 assert(t.value == 42); 270 assert(any_cast<Type&>(a).value == 0); 271 any_cast<Type&>(a).value = 42; // reset the value 272 } 273 assert(Type::count == 1); 274 Type::reset(); 275 // Check getting const Type by value from a non-const rvalue any. 276 // This should cause the const copy constructor to be called. 277 { 278 Type t = any_cast<Type const>(static_cast<any &&>(a)); 279 280 assert(Type::count == 2); 281 assert(Type::copied == 0); 282 assert(Type::const_copied == 0); 283 assert(Type::non_const_copied == 0); 284 assert(Type::moved == 1); 285 assert(t.value == 42); 286 assert(any_cast<Type&>(a).value == 0); 287 any_cast<Type&>(a).value = 42; // reset the value 288 } 289 assert(Type::count == 1); 290 Type::reset(); 291 // Check getting Type by value from a const rvalue any. 292 // This should cause the const copy constructor to be called. 293 { 294 Type t = any_cast<Type>(static_cast<any const&&>(a)); 295 296 assert(Type::count == 2); 297 assert(Type::copied == 1); 298 assert(Type::const_copied == 1); 299 assert(Type::non_const_copied == 0); 300 assert(Type::moved == 0); 301 assert(t.value == 42); 302 assert(any_cast<Type&>(a).value == 42); 303 } 304 // Ensure we still only have 1 Type object alive. 305 assert(Type::count == 1); 306 307 // Check that the original object hasn't been changed. 308 assertContains<Type>(a, 42); 309 } 310 assert(Type::count == 0); 311 } 312 313 int main() { 314 test_cast_is_not_noexcept(); 315 test_cast_return_type(); 316 test_cast_empty(); 317 test_cast_to_reference<small>(); 318 test_cast_to_reference<large>(); 319 test_cast_to_value<small>(); 320 test_cast_to_value<large>(); 321 }