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 // <functional> 10 11 // class function<R(ArgTypes...)> 12 13 // function(const function& f); 14 // function(function&& f); // noexcept in C++20 15 16 // This test runs in C++03, but we have deprecated using std::function in C++03. 17 // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS 18 19 #include <functional> 20 #include <memory> 21 #include <cstdlib> 22 #include <cassert> 23 24 #include "test_macros.h" 25 #include "count_new.h" 26 27 class A 28 { 29 int data_[10]; 30 public: 31 static int count; 32 33 A() 34 { 35 ++count; 36 for (int i = 0; i < 10; ++i) 37 data_[i] = i; 38 } 39 40 A(const A&) {++count;} 41 42 ~A() {--count;} 43 44 int operator()(int i) const 45 { 46 for (int j = 0; j < 10; ++j) 47 i += data_[j]; 48 return i; 49 } 50 }; 51 52 int A::count = 0; 53 54 int g(int) {return 0;} 55 56 int main(int, char**) 57 { 58 globalMemCounter.reset(); 59 assert(globalMemCounter.checkOutstandingNewEq(0)); 60 { 61 std::function<int(int)> f = A(); 62 assert(A::count == 1); 63 assert(globalMemCounter.checkOutstandingNewEq(1)); 64 RTTI_ASSERT(f.target<A>()); 65 RTTI_ASSERT(f.target<int(*)(int)>() == 0); 66 std::function<int(int)> f2 = f; 67 assert(A::count == 2); 68 assert(globalMemCounter.checkOutstandingNewEq(2)); 69 RTTI_ASSERT(f2.target<A>()); 70 RTTI_ASSERT(f2.target<int(*)(int)>() == 0); 71 } 72 assert(A::count == 0); 73 assert(globalMemCounter.checkOutstandingNewEq(0)); 74 { 75 std::function<int(int)> f = g; 76 assert(globalMemCounter.checkOutstandingNewEq(0)); 77 RTTI_ASSERT(f.target<int(*)(int)>()); 78 RTTI_ASSERT(f.target<A>() == 0); 79 std::function<int(int)> f2 = f; 80 assert(globalMemCounter.checkOutstandingNewEq(0)); 81 RTTI_ASSERT(f2.target<int(*)(int)>()); 82 RTTI_ASSERT(f2.target<A>() == 0); 83 } 84 assert(globalMemCounter.checkOutstandingNewEq(0)); 85 { 86 std::function<int(int)> f; 87 assert(globalMemCounter.checkOutstandingNewEq(0)); 88 RTTI_ASSERT(f.target<int(*)(int)>() == 0); 89 RTTI_ASSERT(f.target<A>() == 0); 90 std::function<int(int)> f2 = f; 91 assert(globalMemCounter.checkOutstandingNewEq(0)); 92 RTTI_ASSERT(f2.target<int(*)(int)>() == 0); 93 RTTI_ASSERT(f2.target<A>() == 0); 94 } 95 { 96 std::function<int(int)> f; 97 assert(globalMemCounter.checkOutstandingNewEq(0)); 98 RTTI_ASSERT(f.target<int(*)(int)>() == 0); 99 RTTI_ASSERT(f.target<A>() == 0); 100 assert(!f); 101 std::function<long(int)> g = f; 102 assert(globalMemCounter.checkOutstandingNewEq(0)); 103 RTTI_ASSERT(g.target<long(*)(int)>() == 0); 104 RTTI_ASSERT(g.target<A>() == 0); 105 assert(!g); 106 } 107 #if TEST_STD_VER >= 11 108 assert(globalMemCounter.checkOutstandingNewEq(0)); 109 { // Test rvalue references 110 std::function<int(int)> f = A(); 111 assert(A::count == 1); 112 assert(globalMemCounter.checkOutstandingNewEq(1)); 113 RTTI_ASSERT(f.target<A>()); 114 RTTI_ASSERT(f.target<int(*)(int)>() == 0); 115 LIBCPP_ASSERT_NOEXCEPT(std::function<int(int)>(std::move(f))); 116 #if TEST_STD_VER > 17 117 ASSERT_NOEXCEPT(std::function<int(int)>(std::move(f))); 118 #endif 119 std::function<int(int)> f2 = std::move(f); 120 assert(A::count == 1); 121 assert(globalMemCounter.checkOutstandingNewEq(1)); 122 RTTI_ASSERT(f2.target<A>()); 123 RTTI_ASSERT(f2.target<int(*)(int)>() == 0); 124 RTTI_ASSERT(f.target<A>() == 0); 125 RTTI_ASSERT(f.target<int(*)(int)>() == 0); 126 } 127 assert(globalMemCounter.checkOutstandingNewEq(0)); 128 { 129 // Test that moving a function constructed from a reference wrapper 130 // is done without allocating. 131 DisableAllocationGuard g; 132 using Ref = std::reference_wrapper<A>; 133 A a; 134 Ref aref(a); 135 std::function<int(int)> f(aref); 136 assert(A::count == 1); 137 RTTI_ASSERT(f.target<A>() == nullptr); 138 RTTI_ASSERT(f.target<Ref>()); 139 LIBCPP_ASSERT_NOEXCEPT(std::function<int(int)>(std::move(f))); 140 #if TEST_STD_VER > 17 141 ASSERT_NOEXCEPT(std::function<int(int)>(std::move(f))); 142 #endif 143 std::function<int(int)> f2(std::move(f)); 144 assert(A::count == 1); 145 RTTI_ASSERT(f2.target<A>() == nullptr); 146 RTTI_ASSERT(f2.target<Ref>()); 147 #if defined(_LIBCPP_VERSION) 148 RTTI_ASSERT(f.target<Ref>()); // f is unchanged because the target is small 149 #endif 150 } 151 { 152 // Test that moving a function constructed from a function pointer 153 // is done without allocating 154 DisableAllocationGuard guard; 155 using Ptr = int(*)(int); 156 Ptr p = g; 157 std::function<int(int)> f(p); 158 RTTI_ASSERT(f.target<A>() == nullptr); 159 RTTI_ASSERT(f.target<Ptr>()); 160 LIBCPP_ASSERT_NOEXCEPT(std::function<int(int)>(std::move(f))); 161 #if TEST_STD_VER > 17 162 ASSERT_NOEXCEPT(std::function<int(int)>(std::move(f))); 163 #endif 164 std::function<int(int)> f2(std::move(f)); 165 RTTI_ASSERT(f2.target<A>() == nullptr); 166 RTTI_ASSERT(f2.target<Ptr>()); 167 #if defined(_LIBCPP_VERSION) 168 RTTI_ASSERT(f.target<Ptr>()); // f is unchanged because the target is small 169 #endif 170 } 171 #endif // TEST_STD_VER >= 11 172 173 return 0; 174 } 175