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 // template<class F>
16 //   requires CopyConstructible<F> && Callable<F, ArgTypes..>
17 //         && Convertible<Callable<F, ArgTypes...>::result_type
18 //   operator=(F f);
19 
20 #include <functional>
21 #include <cassert>
22 
23 #include "test_macros.h"
24 #include "count_new.h"
25 
26 class A
27 {
28     int data_[10];
29 public:
30     static int count;
31 
A()32     A()
33     {
34         ++count;
35         for (int i = 0; i < 10; ++i)
36             data_[i] = i;
37     }
38 
A(const A &)39     A(const A&) {++count;}
40 
~A()41     ~A() {--count;}
42 
operator ()(int i) const43     int operator()(int i) const
44     {
45         for (int j = 0; j < 10; ++j)
46             i += data_[j];
47         return i;
48     }
49 
foo(int) const50     int foo(int) const {return 1;}
51 };
52 
53 int A::count = 0;
54 
g(int)55 int g(int) {return 0;}
56 
57 #if TEST_STD_VER >= 11
58 struct RValueCallable {
59     template <class ...Args>
operator ()RValueCallable60     void operator()(Args&&...) && {}
61 };
62 struct LValueCallable {
63     template <class ...Args>
operator ()LValueCallable64     void operator()(Args&&...) & {}
65 };
66 #endif
67 
main(int,char **)68 int main(int, char**)
69 {
70     globalMemCounter.reset();
71     assert(globalMemCounter.checkOutstandingNewEq(0));
72     {
73     std::function<int(int)> f;
74     f = A();
75     assert(A::count == 1);
76     assert(globalMemCounter.checkOutstandingNewEq(1));
77     RTTI_ASSERT(f.target<A>());
78     RTTI_ASSERT(f.target<int(*)(int)>() == 0);
79     }
80     assert(A::count == 0);
81     assert(globalMemCounter.checkOutstandingNewEq(0));
82     {
83     std::function<int(int)> f;
84     f = g;
85     assert(globalMemCounter.checkOutstandingNewEq(0));
86     RTTI_ASSERT(f.target<int(*)(int)>());
87     RTTI_ASSERT(f.target<A>() == 0);
88     }
89     assert(globalMemCounter.checkOutstandingNewEq(0));
90     {
91     std::function<int(int)> f;
92     f = (int (*)(int))0;
93     assert(!f);
94     assert(globalMemCounter.checkOutstandingNewEq(0));
95     RTTI_ASSERT(f.target<int(*)(int)>() == 0);
96     RTTI_ASSERT(f.target<A>() == 0);
97     }
98     {
99     std::function<int(const A*, int)> f;
100     f = &A::foo;
101     assert(f);
102     assert(globalMemCounter.checkOutstandingNewEq(0));
103     RTTI_ASSERT(f.target<int (A::*)(int) const>() != 0);
104     }
105     {
106     std::function<void(int)> f;
107     f = &g;
108     assert(f);
109     RTTI_ASSERT(f.target<int(*)(int)>() != 0);
110     f(1);
111     }
112 #if TEST_STD_VER >= 11
113     {
114         using Fn = std::function<void(int, int, int)>;
115         static_assert(std::is_assignable<Fn&, LValueCallable&>::value, "");
116         static_assert(std::is_assignable<Fn&, LValueCallable>::value, "");
117         static_assert(!std::is_assignable<Fn&, RValueCallable&>::value, "");
118         static_assert(!std::is_assignable<Fn&, RValueCallable>::value, "");
119     }
120     {
121         using Fn = std::function<void(int, int, int)>;
122         static_assert(std::is_assignable<Fn&, Fn&&>::value, "");
123     }
124     {
125         using F1 = std::function<void(int, int)>;
126         using F2 = std::function<void(int, int, int)>;
127         static_assert(!std::is_assignable<F1&, F2&&>::value, "");
128     }
129     {
130         using F1 = std::function<int(int, int)>;
131         using F2 = std::function<A  (int, int)>;
132         static_assert(!std::is_assignable<F1&, F2&&>::value, "");
133         static_assert(!std::is_assignable<F2&, F1&&>::value, "");
134     }
135 #endif
136 
137   return 0;
138 }
139