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