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