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 assert(f.target<A>()); 65 assert(f.target<int(*)(int)>() == 0); 66 std::function<int(int)> f2 = f; 67 assert(A::count == 2); 68 assert(globalMemCounter.checkOutstandingNewEq(2)); 69 assert(f2.target<A>()); 70 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 assert(f.target<int(*)(int)>()); 78 assert(f.target<A>() == 0); 79 std::function<int(int)> f2 = f; 80 assert(globalMemCounter.checkOutstandingNewEq(0)); 81 assert(f2.target<int(*)(int)>()); 82 assert(f2.target<A>() == 0); 83 } 84 assert(globalMemCounter.checkOutstandingNewEq(0)); 85 { 86 std::function<int(int)> f; 87 assert(globalMemCounter.checkOutstandingNewEq(0)); 88 assert(f.target<int(*)(int)>() == 0); 89 assert(f.target<A>() == 0); 90 std::function<int(int)> f2 = f; 91 assert(globalMemCounter.checkOutstandingNewEq(0)); 92 assert(f2.target<int(*)(int)>() == 0); 93 assert(f2.target<A>() == 0); 94 } 95 { 96 std::function<int(int)> f; 97 assert(globalMemCounter.checkOutstandingNewEq(0)); 98 assert(f.target<int(*)(int)>() == 0); 99 assert(f.target<A>() == 0); 100 assert(!f); 101 std::function<long(int)> g = f; 102 assert(globalMemCounter.checkOutstandingNewEq(0)); 103 assert(g.target<long(*)(int)>() == 0); 104 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 assert(f.target<A>()); 114 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 assert(f2.target<A>()); 123 assert(f2.target<int(*)(int)>() == 0); 124 assert(f.target<A>() == 0); 125 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 assert(f.target<A>() == nullptr); 138 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 assert(f2.target<A>() == nullptr); 146 assert(f2.target<Ref>()); 147 LIBCPP_ASSERT(f.target<Ref>()); // f is unchanged because the target is small 148 } 149 { 150 // Test that moving a function constructed from a function pointer 151 // is done without allocating 152 DisableAllocationGuard guard; 153 using Ptr = int(*)(int); 154 Ptr p = g; 155 std::function<int(int)> f(p); 156 assert(f.target<A>() == nullptr); 157 assert(f.target<Ptr>()); 158 LIBCPP_ASSERT_NOEXCEPT(std::function<int(int)>(std::move(f))); 159 #if TEST_STD_VER > 17 160 ASSERT_NOEXCEPT(std::function<int(int)>(std::move(f))); 161 #endif 162 std::function<int(int)> f2(std::move(f)); 163 assert(f2.target<A>() == nullptr); 164 assert(f2.target<Ptr>()); 165 LIBCPP_ASSERT(f.target<Ptr>()); // f is unchanged because the target is small 166 } 167 #endif // TEST_STD_VER >= 11 168 169 return 0; 170 } 171