279 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 std::bind(f_void_1, _1)(2);53 assert(count == save_count + 2);54 save_count = count;55 }56 {57 std::bind(f_void_1, 2)();58 assert(count == save_count + 2);59 save_count = count;60 }61 // function pointer62 {63 void (*fp)(int) = f_void_1;64 std::bind(fp, _1)(3);65 assert(count == save_count+3);66 save_count = count;67 }68 {69 void (*fp)(int) = f_void_1;70 std::bind(fp, 3)();71 assert(count == save_count+3);72 save_count = count;73 }74 // functor75 {76 A_void_1 a0;77 std::bind(a0, _1)(4);78 assert(count == save_count+4);79 save_count = count;80 }81 {82 A_void_1 a0;83 std::bind(a0, 4)();84 assert(count == save_count+4);85 save_count = count;86 }87 // member function pointer88 {89 void (A_void_1::*fp)() = &A_void_1::mem1;90 std::bind(fp, _1)(A_void_1());91 assert(count == save_count+1);92 save_count = count;93 A_void_1 a;94 std::bind(fp, _1)(&a);95 assert(count == save_count+1);96 save_count = count;97 }98 {99 void (A_void_1::*fp)() = &A_void_1::mem1;100 std::bind(fp, A_void_1())();101 assert(count == save_count+1);102 save_count = count;103 A_void_1 a;104 std::bind(fp, &a)();105 assert(count == save_count+1);106 save_count = count;107 }108 // const member function pointer109 {110 void (A_void_1::*fp)() const = &A_void_1::mem2;111 std::bind(fp, _1)(A_void_1());112 assert(count == save_count+2);113 save_count = count;114 A_void_1 a;115 std::bind(fp, _1)(&a);116 assert(count == save_count+2);117 save_count = count;118 }119 {120 void (A_void_1::*fp)() const = &A_void_1::mem2;121 std::bind(fp, A_void_1())();122 assert(count == save_count+2);123 save_count = count;124 A_void_1 a;125 std::bind(fp, &a)();126 assert(count == save_count+2);127 save_count = count;128 }129}130 131// 1 arg, return int132 133TEST_CONSTEXPR_CXX20 int f_int_1(int i) {134 return i + 1;135}136 137struct A_int_1 {138 TEST_CONSTEXPR_CXX20 A_int_1() : data_(5) {}139 TEST_CONSTEXPR_CXX20 int operator()(int i) {140 return i - 1;141 }142 143 TEST_CONSTEXPR_CXX20 int mem1() { return 3; }144 TEST_CONSTEXPR_CXX20 int mem2() const { return 4; }145 int data_;146};147 148TEST_CONSTEXPR_CXX20 bool test_int_1() {149 using namespace std::placeholders;150 // function151 {152 assert(std::bind(f_int_1, _1)(2) == 3);153 assert(std::bind(f_int_1, 2)() == 3);154 }155 // function pointer156 {157 int (*fp)(int) = f_int_1;158 assert(std::bind(fp, _1)(3) == 4);159 assert(std::bind(fp, 3)() == 4);160 }161 // functor162 {163 assert(std::bind(A_int_1(), _1)(4) == 3);164 assert(std::bind(A_int_1(), 4)() == 3);165 }166 // member function pointer167 {168 assert(std::bind(&A_int_1::mem1, _1)(A_int_1()) == 3);169 assert(std::bind(&A_int_1::mem1, A_int_1())() == 3);170 A_int_1 a;171 assert(std::bind(&A_int_1::mem1, _1)(&a) == 3);172 assert(std::bind(&A_int_1::mem1, &a)() == 3);173 }174 // const member function pointer175 {176 assert(std::bind(&A_int_1::mem2, _1)(A_int_1()) == 4);177 assert(std::bind(&A_int_1::mem2, A_int_1())() == 4);178 A_int_1 a;179 assert(std::bind(&A_int_1::mem2, _1)(&a) == 4);180 assert(std::bind(&A_int_1::mem2, &a)() == 4);181 }182 // member data pointer183 {184 assert(std::bind(&A_int_1::data_, _1)(A_int_1()) == 5);185 assert(std::bind(&A_int_1::data_, A_int_1())() == 5);186 A_int_1 a;187 assert(std::bind(&A_int_1::data_, _1)(a) == 5);188 std::bind(&A_int_1::data_, _1)(a) = 6;189 assert(std::bind(&A_int_1::data_, _1)(a) == 6);190 assert(std::bind(&A_int_1::data_, _1)(&a) == 6);191 std::bind(&A_int_1::data_, _1)(&a) = 7;192 assert(std::bind(&A_int_1::data_, _1)(&a) == 7);193 }194 return true;195}196 197// 2 arg, return void198 199void f_void_2(int i, int j)200{201 count += i+j;202}203 204struct A_void_2205{206 void operator()(int i, int j)207 {208 count += i+j;209 }210 211 void mem1(int i) {count += i;}212 void mem2(int i) const {count += i;}213};214 215void216test_void_2()217{218 using namespace std::placeholders;219 int save_count = count;220 // function221 {222 std::bind(f_void_2, _1, _2)(2, 3);223 assert(count == save_count+5);224 save_count = count;225 std::bind(f_void_2, 2, _1)(3);226 assert(count == save_count+5);227 save_count = count;228 std::bind(f_void_2, 2, 3)();229 assert(count == save_count+5);230 save_count = count;231 }232 // member function pointer233 {234 std::bind(&A_void_2::mem1, _1, _2)(A_void_2(), 3);235 assert(count == save_count+3);236 save_count = count;237 std::bind(&A_void_2::mem1, _2, _1)(3, A_void_2());238 assert(count == save_count+3);239 save_count = count;240 }241}242 243TEST_CONSTEXPR_CXX20 int f_nested(int i) {244 return i+1;245}246 247TEST_CONSTEXPR_CXX20 int g_nested(int i) {248 return i*10;249}250 251TEST_CONSTEXPR_CXX20 bool test_nested() {252 using namespace std::placeholders;253 assert(std::bind(f_nested, std::bind(g_nested, _1))(3) == 31);254 return true;255}256 257TEST_CONSTEXPR_CXX20 bool test_many_args() {258 using namespace std::placeholders;259 auto f = [](int a, char, float, long) { return a; };260 auto bound = std::bind(f, _4, _3, _2, _1);261 assert(bound(0l, 1.0f, '2', 3) == 3);262 return true;263}264 265int main(int, char**) {266 test_void_1();267 test_int_1();268 test_void_2();269 test_nested();270 271 // The other tests are not constexpr-friendly since they need to use a global variable272#if TEST_STD_VER >= 20273 static_assert(test_int_1());274 static_assert(test_nested());275#endif276 277 return 0;278}279