305 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 11// <functional>12 13// template<CopyConstructible Fn, CopyConstructible... Types>14// unspecified bind(Fn, Types...); // constexpr since C++2015// template<Returnable R, CopyConstructible Fn, CopyConstructible... Types>16// unspecified bind(Fn, Types...); // constexpr since C++2017 18#include <stdio.h>19 20#include <functional>21#include <cassert>22 23#include "test_macros.h"24 25int count = 0;26 27// 1 arg, return void28 29void f_void_1(int i)30{31 count += i;32}33 34struct A_void_135{36 void operator()(int i)37 {38 count += i;39 }40 41 void mem1() {++count;}42 void mem2() const {count += 2;}43};44 45void46test_void_1()47{48 using namespace std::placeholders;49 int save_count = count;50 // function51 {52 int i = 2;53 std::bind(f_void_1, _1)(i);54 assert(count == save_count + 2);55 save_count = count;56 }57 {58 int i = 2;59 std::bind(f_void_1, i)();60 assert(count == save_count + 2);61 save_count = count;62 }63 // function pointer64 {65 void (*fp)(int) = f_void_1;66 int i = 3;67 std::bind(fp, _1)(i);68 assert(count == save_count+3);69 save_count = count;70 }71 {72 void (*fp)(int) = f_void_1;73 int i = 3;74 std::bind(fp, i)();75 assert(count == save_count+3);76 save_count = count;77 }78 // functor79 {80 A_void_1 a0;81 int i = 4;82 std::bind(a0, _1)(i);83 assert(count == save_count+4);84 save_count = count;85 }86 {87 A_void_1 a0;88 int i = 4;89 std::bind(a0, i)();90 assert(count == save_count+4);91 save_count = count;92 }93 // member function pointer94 {95 void (A_void_1::*fp)() = &A_void_1::mem1;96 A_void_1 a;97 std::bind(fp, _1)(a);98 assert(count == save_count+1);99 save_count = count;100 A_void_1* ap = &a;101 std::bind(fp, _1)(ap);102 assert(count == save_count+1);103 save_count = count;104 }105 {106 void (A_void_1::*fp)() = &A_void_1::mem1;107 A_void_1 a;108 std::bind(fp, a)();109 assert(count == save_count+1);110 save_count = count;111 A_void_1* ap = &a;112 std::bind(fp, ap)();113 assert(count == save_count+1);114 save_count = count;115 }116 // const member function pointer117 {118 void (A_void_1::*fp)() const = &A_void_1::mem2;119 A_void_1 a;120 std::bind(fp, _1)(a);121 assert(count == save_count+2);122 save_count = count;123 A_void_1* ap = &a;124 std::bind(fp, _1)(ap);125 assert(count == save_count+2);126 save_count = count;127 }128 {129 void (A_void_1::*fp)() const = &A_void_1::mem2;130 A_void_1 a;131 std::bind(fp, a)();132 assert(count == save_count+2);133 save_count = count;134 A_void_1* ap = &a;135 std::bind(fp, ap)();136 assert(count == save_count+2);137 save_count = count;138 }139}140 141// 1 arg, return int142 143TEST_CONSTEXPR_CXX20 int f_int_1(int i) {144 return i + 1;145}146 147struct A_int_1 {148 TEST_CONSTEXPR_CXX20 A_int_1() : data_(5) {}149 TEST_CONSTEXPR_CXX20 int operator()(int i) {150 return i - 1;151 }152 153 TEST_CONSTEXPR_CXX20 int mem1() { return 3; }154 TEST_CONSTEXPR_CXX20 int mem2() const { return 4; }155 int data_;156};157 158TEST_CONSTEXPR_CXX20 bool test_int_1() {159 using namespace std::placeholders;160 // function161 {162 int i = 2;163 assert(std::bind(f_int_1, _1)(i) == 3);164 assert(std::bind(f_int_1, i)() == 3);165 }166 // function pointer167 {168 int (*fp)(int) = f_int_1;169 int i = 3;170 assert(std::bind(fp, _1)(i) == 4);171 assert(std::bind(fp, i)() == 4);172 }173 // functor174 {175 int i = 4;176 assert(std::bind(A_int_1(), _1)(i) == 3);177 assert(std::bind(A_int_1(), i)() == 3);178 }179 // member function pointer180 {181 A_int_1 a;182 assert(std::bind(&A_int_1::mem1, _1)(a) == 3);183 assert(std::bind(&A_int_1::mem1, a)() == 3);184 A_int_1* ap = &a;185 assert(std::bind(&A_int_1::mem1, _1)(ap) == 3);186 assert(std::bind(&A_int_1::mem1, ap)() == 3);187 }188 // const member function pointer189 {190 A_int_1 a;191 assert(std::bind(&A_int_1::mem2, _1)(A_int_1()) == 4);192 assert(std::bind(&A_int_1::mem2, A_int_1())() == 4);193 A_int_1* ap = &a;194 assert(std::bind(&A_int_1::mem2, _1)(ap) == 4);195 assert(std::bind(&A_int_1::mem2, ap)() == 4);196 }197 // member data pointer198 {199 A_int_1 a;200 assert(std::bind(&A_int_1::data_, _1)(a) == 5);201 assert(std::bind(&A_int_1::data_, a)() == 5);202 A_int_1* ap = &a;203 assert(std::bind(&A_int_1::data_, _1)(a) == 5);204 std::bind(&A_int_1::data_, _1)(a) = 6;205 assert(std::bind(&A_int_1::data_, _1)(a) == 6);206 assert(std::bind(&A_int_1::data_, _1)(ap) == 6);207 std::bind(&A_int_1::data_, _1)(ap) = 7;208 assert(std::bind(&A_int_1::data_, _1)(ap) == 7);209 }210 211 return true;212}213 214// 2 arg, return void215 216void f_void_2(int i, int j)217{218 count += i+j;219}220 221struct A_void_2222{223 void operator()(int i, int j)224 {225 count += i+j;226 }227 228 void mem1(int i) {count += i;}229 void mem2(int i) const {count += i;}230};231 232void233test_void_2()234{235 using namespace std::placeholders;236 int save_count = count;237 // function238 {239 int i = 2;240 int j = 3;241 std::bind(f_void_2, _1, _2)(i, j);242 assert(count == save_count+5);243 save_count = count;244 std::bind(f_void_2, i, _1)(j);245 assert(count == save_count+5);246 save_count = count;247 std::bind(f_void_2, i, j)();248 assert(count == save_count+5);249 save_count = count;250 }251 // member function pointer252 {253 int j = 3;254 std::bind(&A_void_2::mem1, _1, _2)(A_void_2(), j);255 assert(count == save_count+3);256 save_count = count;257 std::bind(&A_void_2::mem1, _2, _1)(j, A_void_2());258 assert(count == save_count+3);259 save_count = count;260 }261}262 263struct ConstQualifiedMemberFunction {264 TEST_CONSTEXPR_CXX20 bool foo(unsigned long long) const {265 return true;266 }267};268 269TEST_CONSTEXPR_CXX20 bool test_const_qualified_member() {270 using namespace std;271 using namespace std::placeholders;272 const auto f = bind(&ConstQualifiedMemberFunction::foo, _1, 0UL);273 const ConstQualifiedMemberFunction n = ConstQualifiedMemberFunction{};274 bool b = f(n);275 assert(b);276 return true;277}278 279TEST_CONSTEXPR_CXX20 bool test_many_args() {280 using namespace std::placeholders;281 auto f = [](int& a, char&, float&, long&) -> int& { return a; };282 auto bound = std::bind(f, _4, _3, _2, _1);283 int a = 3; char b = '2'; float c = 1.0f; long d = 0l;284 int& result = bound(d, c, b, a);285 assert(&result == &a);286 return true;287}288 289int main(int, char**) {290 test_void_1();291 test_int_1();292 test_void_2();293 test_const_qualified_member();294 test_many_args();295 296 // The other tests are not constexpr-friendly since they need to use a global variable297#if TEST_STD_VER >= 20298 static_assert(test_int_1());299 static_assert(test_const_qualified_member());300 static_assert(test_many_args());301#endif302 303 return 0;304}305