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);
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 
31     A()
32     {
33         ++count;
34         for (int i = 0; i < 10; ++i)
35             data_[i] = i;
36     }
37 
38     A(const A&) {++count;}
39 
40     ~A() {--count;}
41 
42     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 
52 int g(int) {return 0;}
53 
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         std::function<int(int)> f2 = std::move(f);
113         assert(A::count == 1);
114         assert(globalMemCounter.checkOutstandingNewEq(1));
115         assert(f2.target<A>());
116         assert(f2.target<int(*)(int)>() == 0);
117         assert(f.target<A>() == 0);
118         assert(f.target<int(*)(int)>() == 0);
119     }
120     assert(globalMemCounter.checkOutstandingNewEq(0));
121     {
122         // Test that moving a function constructed from a reference wrapper
123         // is done without allocating.
124         DisableAllocationGuard g;
125         using Ref = std::reference_wrapper<A>;
126         A a;
127         Ref aref(a);
128         std::function<int(int)> f(aref);
129         assert(A::count == 1);
130         assert(f.target<A>() == nullptr);
131         assert(f.target<Ref>());
132         std::function<int(int)> f2(std::move(f));
133         assert(A::count == 1);
134         assert(f2.target<A>() == nullptr);
135         assert(f2.target<Ref>());
136         LIBCPP_ASSERT(f.target<Ref>()); // f is unchanged because the target is small
137     }
138     {
139         // Test that moving a function constructed from a function pointer
140         // is done without allocating
141         DisableAllocationGuard guard;
142         using Ptr = int(*)(int);
143         Ptr p = g;
144         std::function<int(int)> f(p);
145         assert(f.target<A>() == nullptr);
146         assert(f.target<Ptr>());
147         std::function<int(int)> f2(std::move(f));
148         assert(f2.target<A>() == nullptr);
149         assert(f2.target<Ptr>());
150         LIBCPP_ASSERT(f.target<Ptr>()); // f is unchanged because the target is small
151     }
152 #endif  // TEST_STD_VER >= 11
153 }
154