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 // <functional> 10 // REQUIRES: c++03 || c++11 || c++14 11 12 // class function<R(ArgTypes...)> 13 14 // template<class F, class A> function(allocator_arg_t, const A&, F); 15 16 // This test runs in C++03, but we have deprecated using std::function in C++03. 17 // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS 18 19 #include <functional> 20 #include <cassert> 21 22 #include "test_macros.h" 23 #include "min_allocator.h" 24 #include "test_allocator.h" 25 #include "count_new.h" 26 #include "../function_types.h" 27 28 #if TEST_STD_VER >= 11 29 struct RValueCallable { 30 template <class ...Args> 31 void operator()(Args&&...) && {} 32 }; 33 struct LValueCallable { 34 template <class ...Args> 35 void operator()(Args&&...) & {} 36 }; 37 #endif 38 39 test_allocator_statistics alloc_stats; 40 41 class DummyClass {}; 42 43 template <class FuncType, class AllocType> 44 void test_FunctionObject(AllocType& alloc) 45 { 46 assert(globalMemCounter.checkOutstandingNewEq(0)); 47 { 48 FunctionObject target; 49 assert(FunctionObject::count == 1); 50 assert(globalMemCounter.checkOutstandingNewEq(0)); 51 std::function<FuncType> f2(std::allocator_arg, alloc, target); 52 assert(FunctionObject::count == 2); 53 assert(globalMemCounter.checkOutstandingNewEq(1)); 54 assert(f2.template target<FunctionObject>()); 55 assert(f2.template target<FuncType>() == 0); 56 assert(f2.template target<FuncType*>() == 0); 57 } 58 assert(FunctionObject::count == 0); 59 assert(globalMemCounter.checkOutstandingNewEq(0)); 60 } 61 62 63 template <class FuncType, class AllocType> 64 void test_FreeFunction(AllocType& alloc) 65 { 66 assert(globalMemCounter.checkOutstandingNewEq(0)); 67 { 68 FuncType* target = &FreeFunction; 69 assert(globalMemCounter.checkOutstandingNewEq(0)); 70 std::function<FuncType> f2(std::allocator_arg, alloc, target); 71 // The allocator may not fit in the small object buffer, if we allocated 72 // check it was done via the allocator. 73 assert(globalMemCounter.checkOutstandingNewEq(alloc_stats.alloc_count)); 74 assert(f2.template target<FuncType*>()); 75 assert(*f2.template target<FuncType*>() == target); 76 assert(f2.template target<FuncType>() == 0); 77 assert(f2.template target<DummyClass>() == 0); 78 } 79 assert(globalMemCounter.checkOutstandingNewEq(0)); 80 } 81 82 template <class TargetType, class FuncType, class AllocType> 83 void test_MemFunClass(AllocType& alloc) 84 { 85 assert(globalMemCounter.checkOutstandingNewEq(0)); 86 { 87 TargetType target = &MemFunClass::foo; 88 assert(globalMemCounter.checkOutstandingNewEq(0)); 89 std::function<FuncType> f2(std::allocator_arg, alloc, target); 90 assert(globalMemCounter.checkOutstandingNewEq(alloc_stats.alloc_count)); 91 assert(f2.template target<TargetType>()); 92 assert(*f2.template target<TargetType>() == target); 93 assert(f2.template target<FuncType*>() == 0); 94 } 95 assert(globalMemCounter.checkOutstandingNewEq(0)); 96 } 97 98 template <class Alloc> 99 void test_for_alloc(Alloc& alloc) { 100 test_FunctionObject<int()>(alloc); 101 test_FunctionObject<int(int)>(alloc); 102 test_FunctionObject<int(int, int)>(alloc); 103 test_FunctionObject<int(int, int, int)>(alloc); 104 105 test_FreeFunction<int()>(alloc); 106 test_FreeFunction<int(int)>(alloc); 107 test_FreeFunction<int(int, int)>(alloc); 108 test_FreeFunction<int(int, int, int)>(alloc); 109 110 test_MemFunClass<int(MemFunClass::*)() const, int(MemFunClass&)>(alloc); 111 test_MemFunClass<int(MemFunClass::*)(int) const, int(MemFunClass&, int)>(alloc); 112 test_MemFunClass<int(MemFunClass::*)(int, int) const, int(MemFunClass&, int, int)>(alloc); 113 } 114 115 int main(int, char**) { 116 globalMemCounter.reset(); 117 { 118 bare_allocator<DummyClass> bare_alloc; 119 test_for_alloc(bare_alloc); 120 } 121 { 122 non_default_test_allocator<DummyClass> non_default_alloc(42, &alloc_stats); 123 test_for_alloc(non_default_alloc); 124 } 125 #if TEST_STD_VER >= 11 126 { 127 using Fn = std::function<void(int, int, int)>; 128 static_assert(std::is_constructible<Fn, std::allocator_arg_t, std::allocator<int>, LValueCallable&>::value, ""); 129 static_assert(std::is_constructible<Fn, std::allocator_arg_t, std::allocator<int>, LValueCallable>::value, ""); 130 static_assert(!std::is_constructible<Fn, std::allocator_arg_t, std::allocator<int>, RValueCallable&>::value, ""); 131 static_assert(!std::is_constructible<Fn, std::allocator_arg_t, std::allocator<int>, RValueCallable>::value, ""); 132 } 133 #endif 134 135 136 return 0; 137 } 138