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