1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // UNSUPPORTED: c++03, c++11, c++14 10 11 // Throwing bad_any_cast is supported starting in macosx10.13 12 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12}} && !no-exceptions 13 14 // <any> 15 16 // template <class Value> any(Value &&) 17 18 // Test construction from a value. 19 // Concerns: 20 // --------- 21 // 1. The value is properly move/copied depending on the value category. 22 // 2. Both small and large values are properly handled. 23 24 25 #include <any> 26 #include <cassert> 27 28 #include "any_helpers.h" 29 #include "count_new.h" 30 #include "test_macros.h" 31 32 using std::any; 33 using std::any_cast; 34 35 template <class Type> 36 void test_copy_value_throws() 37 { 38 #if !defined(TEST_HAS_NO_EXCEPTIONS) 39 assert(Type::count == 0); 40 { 41 Type const t(42); 42 assert(Type::count == 1); 43 try { 44 any const a2(t); 45 assert(false); 46 } catch (my_any_exception const &) { 47 // do nothing 48 } catch (...) { 49 assert(false); 50 } 51 assert(Type::count == 1); 52 assert(t.value == 42); 53 } 54 assert(Type::count == 0); 55 #endif 56 } 57 58 void test_move_value_throws() 59 { 60 #if !defined(TEST_HAS_NO_EXCEPTIONS) 61 assert(throws_on_move::count == 0); 62 { 63 throws_on_move v; 64 assert(throws_on_move::count == 1); 65 try { 66 any const a(std::move(v)); 67 assert(false); 68 } catch (my_any_exception const &) { 69 // do nothing 70 } catch (...) { 71 assert(false); 72 } 73 assert(throws_on_move::count == 1); 74 } 75 assert(throws_on_move::count == 0); 76 #endif 77 } 78 79 template <class Type> 80 void test_copy_move_value() { 81 // constructing from a small type should perform no allocations. 82 DisableAllocationGuard g(isSmallType<Type>()); ((void)g); 83 assert(Type::count == 0); 84 Type::reset(); 85 { 86 Type t(42); 87 assert(Type::count == 1); 88 89 any a(t); 90 91 assert(Type::count == 2); 92 assert(Type::copied == 1); 93 assert(Type::moved == 0); 94 assertContains<Type>(a, 42); 95 } 96 assert(Type::count == 0); 97 Type::reset(); 98 { 99 Type t(42); 100 assert(Type::count == 1); 101 102 any a(std::move(t)); 103 104 assert(Type::count == 2); 105 assert(Type::copied == 0); 106 assert(Type::moved == 1); 107 assertContains<Type>(a, 42); 108 } 109 } 110 111 // Test that any(ValueType&&) is *never* selected for a std::in_place_type_t specialization. 112 void test_sfinae_constraints() { 113 using BadTag = std::in_place_type_t<int>; 114 using OKTag = std::in_place_t; 115 // Test that the tag type is properly handled in SFINAE 116 BadTag t = std::in_place_type<int>; 117 OKTag ot = std::in_place; 118 { 119 std::any a(t); 120 assertContains<int>(a, 0); 121 } 122 { 123 std::any a(std::move(t)); 124 assertContains<int>(a, 0); 125 } 126 { 127 std::any a(ot); 128 assert(containsType<OKTag>(a)); 129 } 130 { 131 struct Dummy { Dummy() = delete; }; 132 using T = std::in_place_type_t<Dummy>; 133 static_assert(!std::is_constructible<std::any, T>::value, ""); 134 } 135 { 136 // Test that the ValueType&& constructor SFINAE's away when the 137 // argument is non-copyable 138 struct NoCopy { 139 NoCopy() = default; 140 NoCopy(NoCopy const&) = delete; 141 NoCopy(int) {} 142 }; 143 static_assert(!std::is_constructible<std::any, NoCopy>::value, ""); 144 static_assert(!std::is_constructible<std::any, NoCopy&>::value, ""); 145 static_assert(!std::is_convertible<NoCopy, std::any>::value, ""); 146 } 147 } 148 149 int main(int, char**) { 150 test_copy_move_value<small>(); 151 test_copy_move_value<large>(); 152 test_copy_value_throws<small_throws_on_copy>(); 153 test_copy_value_throws<large_throws_on_copy>(); 154 test_move_value_throws(); 155 test_sfinae_constraints(); 156 157 return 0; 158 } 159