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 // UNSUPPORTED: c++03
10 
11 // <functional>
12 
13 // class function<R(ArgTypes...)>
14 
15 // function& operator=(const function& f);
16 
17 #include <cassert>
18 #include <functional>
19 #include <utility>
20 
21 #include "test_macros.h"
22 #include "count_new.h"
23 
24 class A {
25   int data_[10];
26 
27 public:
28   static int count;
29 
A()30   A() {
31     ++count;
32     for (int i = 0; i < 10; ++i)
33       data_[i] = i;
34   }
35 
A(const A &)36   A(const A &) { ++count; }
37 
~A()38   ~A() { --count; }
39 
operator ()(int i) const40   int operator()(int i) const {
41     for (int j = 0; j < 10; ++j)
42       i += data_[j];
43     return i;
44   }
45 };
46 
47 int A::count = 0;
48 
g0()49 int g0() { return 0; }
g(int)50 int g(int) { return 0; }
g2(int,int)51 int g2(int, int) { return 2; }
g3(int,int,int)52 int g3(int, int, int) { return 3; }
53 
main(int,char **)54 int main(int, char**) {
55   globalMemCounter.reset();
56   assert(globalMemCounter.checkOutstandingNewEq(0));
57   {
58     std::function<int(int)> f = A();
59     assert(A::count == 1);
60     assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
61     RTTI_ASSERT(f.target<A>());
62     RTTI_ASSERT(f.target<int (*)(int)>() == 0);
63     std::function<int(int)> f2;
64     f2 = f;
65     assert(A::count == 2);
66     assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(2));
67     RTTI_ASSERT(f2.target<A>());
68     RTTI_ASSERT(f2.target<int (*)(int)>() == 0);
69   }
70   assert(A::count == 0);
71   assert(globalMemCounter.checkOutstandingNewEq(0));
72   {
73     std::function<int(int)> f = g;
74     assert(globalMemCounter.checkOutstandingNewEq(0));
75     RTTI_ASSERT(f.target<int (*)(int)>());
76     RTTI_ASSERT(f.target<A>() == 0);
77     std::function<int(int)> f2;
78     f2 = f;
79     assert(globalMemCounter.checkOutstandingNewEq(0));
80     RTTI_ASSERT(f2.target<int (*)(int)>());
81     RTTI_ASSERT(f2.target<A>() == 0);
82   }
83   assert(globalMemCounter.checkOutstandingNewEq(0));
84   {
85     std::function<int(int)> f;
86     assert(globalMemCounter.checkOutstandingNewEq(0));
87     RTTI_ASSERT(f.target<int (*)(int)>() == 0);
88     RTTI_ASSERT(f.target<A>() == 0);
89     std::function<int(int)> f2;
90     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     typedef std::function<int()> Func;
97     Func f = g0;
98     Func& fr = (f = (Func &)f);
99     assert(&fr == &f);
100     RTTI_ASSERT(*f.target<int(*)()>() == g0);
101   }
102   {
103     typedef std::function<int(int)> Func;
104     Func f = g;
105     Func& fr = (f = (Func &)f);
106     assert(&fr == &f);
107     RTTI_ASSERT(*f.target<int(*)(int)>() == g);
108   }
109   {
110     typedef std::function<int(int, int)> Func;
111     Func f = g2;
112     Func& fr = (f = (Func &)f);
113     assert(&fr == &f);
114     RTTI_ASSERT(*f.target<int(*)(int, int)>() == g2);
115   }
116   {
117     typedef std::function<int(int, int, int)> Func;
118     Func f = g3;
119     Func& fr = (f = (Func &)f);
120     assert(&fr == &f);
121     RTTI_ASSERT(*f.target<int(*)(int, int, int)>() == g3);
122   }
123 #if TEST_STD_VER >= 11
124   assert(globalMemCounter.checkOutstandingNewEq(0));
125   {
126     std::function<int(int)> f = A();
127     assert(A::count == 1);
128     assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
129     RTTI_ASSERT(f.target<A>());
130     RTTI_ASSERT(f.target<int (*)(int)>() == 0);
131     std::function<int(int)> f2;
132     f2 = std::move(f);
133     assert(A::count == 1);
134     assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
135     RTTI_ASSERT(f2.target<A>());
136     RTTI_ASSERT(f2.target<int (*)(int)>() == 0);
137     RTTI_ASSERT(f.target<A>() == 0);
138     RTTI_ASSERT(f.target<int (*)(int)>() == 0);
139   }
140 #endif
141 
142   return 0;
143 }
144