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