113 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++0310// REQUIRES: c++11 || c++1411 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++1719 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 28class A29{30 int data_[10];31public: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) const46 {47 for (int j = 0; j < 10; ++j)48 i += data_[j];49 return i;50 }51};52 53int A::count = 0;54 55int g(int) { return 0; }56 57int 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 RTTI_ASSERT(f.target<A>());66 RTTI_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 RTTI_ASSERT(f2.target<A>());72 RTTI_ASSERT(f2.target<int (*)(int)>() == 0);73 RTTI_ASSERT(f.target<A>() == 0);74 RTTI_ASSERT(f.target<int (*)(int)>() == 0);75 }76 assert(globalMemCounter.checkOutstandingNewEq(0));77 {78 // Test that moving a function constructed from a reference wrapper79 // 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 RTTI_ASSERT(f.target<A>() == nullptr);87 RTTI_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 RTTI_ASSERT(f2.target<A>() == nullptr);92 RTTI_ASSERT(f2.target<Ref>());93 RTTI_ASSERT(f.target<Ref>()); // f is unchanged because the target is small94 }95 {96 // Test that moving a function constructed from a function pointer97 // is done without allocating98 DisableAllocationGuard guard;99 using Ptr = int(*)(int);100 Ptr p = g;101 std::function<int(int)> f(p);102 RTTI_ASSERT(f.target<A>() == nullptr);103 RTTI_ASSERT(f.target<Ptr>());104 std::function<int(int)> f2(std::allocator_arg, std::allocator<int>(),105 std::move(f));106 RTTI_ASSERT(f2.target<A>() == nullptr);107 RTTI_ASSERT(f2.target<Ptr>());108 RTTI_ASSERT(f.target<Ptr>()); // f is unchanged because the target is small109 }110 111 return 0;112}113