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