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 // REQUIRES: c++11 || c++14 11 12 // <functional> 13 14 // class function<R(ArgTypes...)> 15 16 // template<class A> function(allocator_arg_t, const A&, function&&); 17 // 18 // This signature was removed in C++17 19 20 #include <functional> 21 #include <memory> 22 #include <cassert> 23 24 #include "test_macros.h" 25 #include "min_allocator.h" 26 #include "count_new.h" 27 28 class A 29 { 30 int data_[10]; 31 public: 32 static int count; 33 34 A() 35 { 36 ++count; 37 for (int i = 0; i < 10; ++i) 38 data_[i] = i; 39 } 40 41 A(const A&) {++count;} 42 43 ~A() {--count;} 44 45 int operator()(int i) const 46 { 47 for (int j = 0; j < 10; ++j) 48 i += data_[j]; 49 return i; 50 } 51 }; 52 53 int A::count = 0; 54 55 int g(int) { return 0; } 56 57 int main(int, char**) 58 { 59 globalMemCounter.reset(); 60 assert(globalMemCounter.checkOutstandingNewEq(0)); 61 { 62 std::function<int(int)> f = A(); 63 assert(A::count == 1); 64 assert(globalMemCounter.checkOutstandingNewEq(1)); 65 assert(f.target<A>()); 66 assert(f.target<int (*)(int)>() == 0); 67 std::function<int(int)> f2(std::allocator_arg, bare_allocator<A>(), 68 std::move(f)); 69 assert(A::count == 1); 70 assert(globalMemCounter.checkOutstandingNewEq(1)); 71 assert(f2.target<A>()); 72 assert(f2.target<int (*)(int)>() == 0); 73 assert(f.target<A>() == 0); 74 assert(f.target<int (*)(int)>() == 0); 75 } 76 assert(globalMemCounter.checkOutstandingNewEq(0)); 77 { 78 // Test that moving a function constructed from a reference wrapper 79 // is done without allocating. 80 DisableAllocationGuard g; 81 using Ref = std::reference_wrapper<A>; 82 A a; 83 Ref aref(a); 84 std::function<int(int)> f(aref); 85 assert(A::count == 1); 86 assert(f.target<A>() == nullptr); 87 assert(f.target<Ref>()); 88 std::function<int(int)> f2(std::allocator_arg, std::allocator<int>{}, 89 std::move(f)); 90 assert(A::count == 1); 91 assert(f2.target<A>() == nullptr); 92 assert(f2.target<Ref>()); 93 assert(f.target<Ref>()); // f is unchanged because the target is small 94 } 95 { 96 // Test that moving a function constructed from a function pointer 97 // is done without allocating 98 DisableAllocationGuard guard; 99 using Ptr = int(*)(int); 100 Ptr p = g; 101 std::function<int(int)> f(p); 102 assert(f.target<A>() == nullptr); 103 assert(f.target<Ptr>()); 104 std::function<int(int)> f2(std::allocator_arg, std::allocator<int>(), 105 std::move(f)); 106 assert(f2.target<A>() == nullptr); 107 assert(f2.target<Ptr>()); 108 assert(f.target<Ptr>()); // f is unchanged because the target is small 109 } 110 111 return 0; 112 } 113