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 11 12 // <experimental/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 <experimental/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::experimental::any; 32 using std::experimental::any_cast; 33 using std::experimental::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 any_cast<Type>(static_cast<any&&>(a)); 95 assert(false); 96 } catch (bad_any_cast const &) { 97 // do nothing 98 } catch (...) { 99 assert(false); 100 } 101 #endif 102 } 103 104 void test_cast_empty() { 105 // None of these operations should allocate. 106 DisableAllocationGuard g; ((void)g); 107 any a; 108 checkThrows<int>(a); 109 } 110 111 template <class Type> 112 void test_cast_to_reference() { 113 assert(Type::count == 0); 114 Type::reset(); 115 { 116 any a((Type(42))); 117 any const& ca = a; 118 assert(Type::count == 1); 119 assert(Type::copied == 0); 120 assert(Type::moved == 1); 121 122 // Try a cast to a bad type. 123 // NOTE: Type cannot be an int. 124 checkThrows<int>(a); 125 checkThrows<int&, int const&>(a); 126 checkThrows<Type*, Type const*>(a); 127 checkThrows<Type const*>(a); 128 129 // Check getting a type by reference from a non-const lvalue any. 130 { 131 Type& v = any_cast<Type&>(a); 132 assert(v.value == 42); 133 134 Type const &cv = any_cast<Type const&>(a); 135 assert(&cv == &v); 136 } 137 // Check getting a type by reference from a const lvalue any. 138 { 139 Type const& v = any_cast<Type const&>(ca); 140 assert(v.value == 42); 141 142 Type const &cv = any_cast<Type const&>(ca); 143 assert(&cv == &v); 144 } 145 // Check getting a type by reference from a non-const rvalue 146 { 147 Type& v = any_cast<Type&>(std::move(a)); 148 assert(v.value == 42); 149 150 Type const &cv = any_cast<Type const&>(std::move(a)); 151 assert(&cv == &v); 152 } 153 // Check getting a type by reference from a const rvalue any. 154 { 155 Type const& v = any_cast<Type const&>(std::move(ca)); 156 assert(v.value == 42); 157 158 Type const &cv = any_cast<Type const&>(std::move(ca)); 159 assert(&cv == &v); 160 } 161 162 // Check that the original object hasn't been changed. 163 assertContains<Type>(a, 42); 164 165 // Check that no objects have been created/copied/moved. 166 assert(Type::count == 1); 167 assert(Type::copied == 0); 168 assert(Type::moved == 1); 169 } 170 assert(Type::count == 0); 171 } 172 173 template <class Type> 174 void test_cast_to_value() { 175 assert(Type::count == 0); 176 Type::reset(); 177 { 178 any a((Type(42))); 179 any const& ca = a; 180 assert(Type::count == 1); 181 assert(Type::copied == 0); 182 assert(Type::moved == 1); 183 184 // Try a cast to a bad type. 185 // NOTE: Type cannot be an int. 186 checkThrows<int>(a); 187 checkThrows<int&, int const&>(a); 188 checkThrows<Type*, Type const*>(a); 189 checkThrows<Type const*>(a); 190 191 Type::reset(); // NOTE: reset does not modify Type::count 192 // Check getting Type by value from a non-const lvalue any. 193 // This should cause the non-const copy constructor to be called. 194 { 195 Type t = any_cast<Type>(a); 196 197 assert(Type::count == 2); 198 assert(Type::copied == 1); 199 assert(Type::const_copied == 0); 200 assert(Type::non_const_copied == 1); 201 assert(Type::moved == 0); 202 assert(t.value == 42); 203 } 204 assert(Type::count == 1); 205 Type::reset(); 206 // Check getting const Type by value from a non-const lvalue any. 207 // This should cause the const copy constructor to be called. 208 { 209 Type t = any_cast<Type const>(a); 210 211 assert(Type::count == 2); 212 assert(Type::copied == 1); 213 assert(Type::const_copied == 1); 214 assert(Type::non_const_copied == 0); 215 assert(Type::moved == 0); 216 assert(t.value == 42); 217 } 218 assert(Type::count == 1); 219 Type::reset(); 220 // Check getting Type by value from a non-const lvalue any. 221 // This should cause the const copy constructor to be called. 222 { 223 Type t = any_cast<Type>(static_cast<any const&>(a)); 224 225 assert(Type::count == 2); 226 assert(Type::copied == 1); 227 assert(Type::const_copied == 1); 228 assert(Type::non_const_copied == 0); 229 assert(Type::moved == 0); 230 assert(t.value == 42); 231 } 232 assert(Type::count == 1); 233 Type::reset(); 234 // Check getting Type by value from a non-const rvalue any. 235 // This should cause the non-const copy constructor to be called. 236 { 237 Type t = any_cast<Type>(static_cast<any &&>(a)); 238 239 assert(Type::count == 2); 240 assert(Type::copied == 1); 241 assert(Type::const_copied == 0); 242 assert(Type::non_const_copied == 1); 243 assert(Type::moved == 0); 244 assert(t.value == 42); 245 } 246 assert(Type::count == 1); 247 Type::reset(); 248 // Check getting const Type by value from a non-const rvalue any. 249 // This should cause the const copy constructor to be called. 250 { 251 Type t = any_cast<Type const>(static_cast<any &&>(a)); 252 253 assert(Type::count == 2); 254 assert(Type::copied == 1); 255 assert(Type::const_copied == 1); 256 assert(Type::non_const_copied == 0); 257 assert(Type::moved == 0); 258 assert(t.value == 42); 259 } 260 assert(Type::count == 1); 261 Type::reset(); 262 // Check getting Type by value from a const rvalue any. 263 // This should cause the const copy constructor to be called. 264 { 265 Type t = any_cast<Type>(static_cast<any const&&>(a)); 266 267 assert(Type::count == 2); 268 assert(Type::copied == 1); 269 assert(Type::const_copied == 1); 270 assert(Type::non_const_copied == 0); 271 assert(Type::moved == 0); 272 assert(t.value == 42); 273 } 274 // Ensure we still only have 1 Type object alive. 275 assert(Type::count == 1); 276 277 // Check that the original object hasn't been changed. 278 assertContains<Type>(a, 42); 279 } 280 assert(Type::count == 0); 281 } 282 283 // Even though you can't get a non-copyable class into std::any 284 // the standard requires that these overloads compile and function. 285 void test_non_copyable_ref() { 286 struct no_copy 287 { 288 no_copy() {} 289 no_copy(no_copy &&) {} 290 private: 291 no_copy(no_copy const &); 292 }; 293 294 any a; 295 checkThrows<no_copy &, no_copy const&>(a); 296 checkThrows<no_copy const&>(a); 297 assertEmpty(a); 298 } 299 300 int main() { 301 test_cast_is_not_noexcept(); 302 test_cast_return_type(); 303 test_cast_empty(); 304 test_cast_to_reference<small>(); 305 test_cast_to_reference<large>(); 306 test_cast_to_value<small>(); 307 test_cast_to_value<large>(); 308 test_non_copyable_ref(); 309 } 310