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