1*c8917048SJakub Mazurkiewicz //===----------------------------------------------------------------------===//
2*c8917048SJakub Mazurkiewicz //
3*c8917048SJakub Mazurkiewicz // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*c8917048SJakub Mazurkiewicz // See https://llvm.org/LICENSE.txt for license information.
5*c8917048SJakub Mazurkiewicz // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*c8917048SJakub Mazurkiewicz //
7*c8917048SJakub Mazurkiewicz //===----------------------------------------------------------------------===//
8*c8917048SJakub Mazurkiewicz
9*c8917048SJakub Mazurkiewicz // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10*c8917048SJakub Mazurkiewicz
11*c8917048SJakub Mazurkiewicz // <functional>
12*c8917048SJakub Mazurkiewicz
13*c8917048SJakub Mazurkiewicz // template<class F, class... Args>
14*c8917048SJakub Mazurkiewicz // constexpr unspecified bind_back(F&& f, Args&&... args);
15*c8917048SJakub Mazurkiewicz
16*c8917048SJakub Mazurkiewicz #include <functional>
17*c8917048SJakub Mazurkiewicz
18*c8917048SJakub Mazurkiewicz #include <cassert>
19*c8917048SJakub Mazurkiewicz #include <concepts>
20*c8917048SJakub Mazurkiewicz #include <tuple>
21*c8917048SJakub Mazurkiewicz #include <utility>
22*c8917048SJakub Mazurkiewicz
23*c8917048SJakub Mazurkiewicz #include "callable_types.h"
24*c8917048SJakub Mazurkiewicz #include "types.h"
25*c8917048SJakub Mazurkiewicz
test_basic_bindings()26*c8917048SJakub Mazurkiewicz constexpr void test_basic_bindings() {
27*c8917048SJakub Mazurkiewicz { // Bind arguments, call without arguments
28*c8917048SJakub Mazurkiewicz {
29*c8917048SJakub Mazurkiewicz auto f = std::bind_back(MakeTuple{});
30*c8917048SJakub Mazurkiewicz assert(f() == std::make_tuple());
31*c8917048SJakub Mazurkiewicz }
32*c8917048SJakub Mazurkiewicz {
33*c8917048SJakub Mazurkiewicz auto f = std::bind_back(MakeTuple{}, Elem<1>{});
34*c8917048SJakub Mazurkiewicz assert(f() == std::make_tuple(Elem<1>{}));
35*c8917048SJakub Mazurkiewicz }
36*c8917048SJakub Mazurkiewicz {
37*c8917048SJakub Mazurkiewicz auto f = std::bind_back(MakeTuple{}, Elem<1>{}, Elem<2>{});
38*c8917048SJakub Mazurkiewicz assert(f() == std::make_tuple(Elem<1>{}, Elem<2>{}));
39*c8917048SJakub Mazurkiewicz }
40*c8917048SJakub Mazurkiewicz {
41*c8917048SJakub Mazurkiewicz auto f = std::bind_back(MakeTuple{}, Elem<1>{}, Elem<2>{}, Elem<3>{});
42*c8917048SJakub Mazurkiewicz assert(f() == std::make_tuple(Elem<1>{}, Elem<2>{}, Elem<3>{}));
43*c8917048SJakub Mazurkiewicz }
44*c8917048SJakub Mazurkiewicz }
45*c8917048SJakub Mazurkiewicz
46*c8917048SJakub Mazurkiewicz { // Bind no arguments, call with arguments
47*c8917048SJakub Mazurkiewicz {
48*c8917048SJakub Mazurkiewicz auto f = std::bind_back(MakeTuple{});
49*c8917048SJakub Mazurkiewicz assert(f(Elem<1>{}) == std::make_tuple(Elem<1>{}));
50*c8917048SJakub Mazurkiewicz }
51*c8917048SJakub Mazurkiewicz {
52*c8917048SJakub Mazurkiewicz auto f = std::bind_back(MakeTuple{});
53*c8917048SJakub Mazurkiewicz assert(f(Elem<1>{}, Elem<2>{}) == std::make_tuple(Elem<1>{}, Elem<2>{}));
54*c8917048SJakub Mazurkiewicz }
55*c8917048SJakub Mazurkiewicz {
56*c8917048SJakub Mazurkiewicz auto f = std::bind_back(MakeTuple{});
57*c8917048SJakub Mazurkiewicz assert(f(Elem<1>{}, Elem<2>{}, Elem<3>{}) == std::make_tuple(Elem<1>{}, Elem<2>{}, Elem<3>{}));
58*c8917048SJakub Mazurkiewicz }
59*c8917048SJakub Mazurkiewicz }
60*c8917048SJakub Mazurkiewicz
61*c8917048SJakub Mazurkiewicz { // Bind arguments, call with arguments
62*c8917048SJakub Mazurkiewicz {
63*c8917048SJakub Mazurkiewicz auto f = std::bind_back(MakeTuple{}, Elem<1>{});
64*c8917048SJakub Mazurkiewicz assert(f(Elem<10>{}) == std::make_tuple(Elem<10>{}, Elem<1>{}));
65*c8917048SJakub Mazurkiewicz }
66*c8917048SJakub Mazurkiewicz {
67*c8917048SJakub Mazurkiewicz auto f = std::bind_back(MakeTuple{}, Elem<1>{}, Elem<2>{});
68*c8917048SJakub Mazurkiewicz assert(f(Elem<10>{}) == std::make_tuple(Elem<10>{}, Elem<1>{}, Elem<2>{}));
69*c8917048SJakub Mazurkiewicz }
70*c8917048SJakub Mazurkiewicz {
71*c8917048SJakub Mazurkiewicz auto f = std::bind_back(MakeTuple{}, Elem<1>{}, Elem<2>{}, Elem<3>{});
72*c8917048SJakub Mazurkiewicz assert(f(Elem<10>{}) == std::make_tuple(Elem<10>{}, Elem<1>{}, Elem<2>{}, Elem<3>{}));
73*c8917048SJakub Mazurkiewicz }
74*c8917048SJakub Mazurkiewicz
75*c8917048SJakub Mazurkiewicz {
76*c8917048SJakub Mazurkiewicz auto f = std::bind_back(MakeTuple{}, Elem<1>{});
77*c8917048SJakub Mazurkiewicz assert(f(Elem<10>{}, Elem<11>{}) == std::make_tuple(Elem<10>{}, Elem<11>{}, Elem<1>{}));
78*c8917048SJakub Mazurkiewicz }
79*c8917048SJakub Mazurkiewicz {
80*c8917048SJakub Mazurkiewicz auto f = std::bind_back(MakeTuple{}, Elem<1>{}, Elem<2>{});
81*c8917048SJakub Mazurkiewicz assert(f(Elem<10>{}, Elem<11>{}) == std::make_tuple(Elem<10>{}, Elem<11>{}, Elem<1>{}, Elem<2>{}));
82*c8917048SJakub Mazurkiewicz }
83*c8917048SJakub Mazurkiewicz {
84*c8917048SJakub Mazurkiewicz auto f = std::bind_back(MakeTuple{}, Elem<1>{}, Elem<2>{}, Elem<3>{});
85*c8917048SJakub Mazurkiewicz assert(f(Elem<10>{}, Elem<11>{}) == std::make_tuple(Elem<10>{}, Elem<11>{}, Elem<1>{}, Elem<2>{}, Elem<3>{}));
86*c8917048SJakub Mazurkiewicz }
87*c8917048SJakub Mazurkiewicz {
88*c8917048SJakub Mazurkiewicz auto f = std::bind_back(MakeTuple{}, Elem<1>{}, Elem<2>{}, Elem<3>{});
89*c8917048SJakub Mazurkiewicz assert(f(Elem<10>{}, Elem<11>{}, Elem<12>{}) ==
90*c8917048SJakub Mazurkiewicz std::make_tuple(Elem<10>{}, Elem<11>{}, Elem<12>{}, Elem<1>{}, Elem<2>{}, Elem<3>{}));
91*c8917048SJakub Mazurkiewicz }
92*c8917048SJakub Mazurkiewicz }
93*c8917048SJakub Mazurkiewicz
94*c8917048SJakub Mazurkiewicz { // Basic tests with fundamental types
95*c8917048SJakub Mazurkiewicz int n = 2;
96*c8917048SJakub Mazurkiewicz int m = 1;
97*c8917048SJakub Mazurkiewicz int sum = 0;
98*c8917048SJakub Mazurkiewicz auto add = [](int x, int y) { return x + y; };
99*c8917048SJakub Mazurkiewicz auto add_n = [](int a, int b, int c, int d, int e, int f) { return a + b + c + d + e + f; };
100*c8917048SJakub Mazurkiewicz auto add_ref = [&](int x, int y) -> int& { return sum = x + y; };
101*c8917048SJakub Mazurkiewicz auto add_rref = [&](int x, int y) -> int&& { return std::move(sum = x + y); };
102*c8917048SJakub Mazurkiewicz
103*c8917048SJakub Mazurkiewicz auto a = std::bind_back(add, m, n);
104*c8917048SJakub Mazurkiewicz assert(a() == 3);
105*c8917048SJakub Mazurkiewicz
106*c8917048SJakub Mazurkiewicz auto b = std::bind_back(add_n, m, n, m, m, m, m);
107*c8917048SJakub Mazurkiewicz assert(b() == 7);
108*c8917048SJakub Mazurkiewicz
109*c8917048SJakub Mazurkiewicz auto c = std::bind_back(add_n, n, m);
110*c8917048SJakub Mazurkiewicz assert(c(1, 1, 1, 1) == 7);
111*c8917048SJakub Mazurkiewicz
112*c8917048SJakub Mazurkiewicz auto d = std::bind_back(add_ref, n, m);
113*c8917048SJakub Mazurkiewicz std::same_as<int&> decltype(auto) dresult(d());
114*c8917048SJakub Mazurkiewicz assert(dresult == 3);
115*c8917048SJakub Mazurkiewicz
116*c8917048SJakub Mazurkiewicz auto e = std::bind_back(add_rref, n, m);
117*c8917048SJakub Mazurkiewicz std::same_as<int&&> decltype(auto) eresult(e());
118*c8917048SJakub Mazurkiewicz assert(eresult == 3);
119*c8917048SJakub Mazurkiewicz
120*c8917048SJakub Mazurkiewicz auto f = std::bind_back(add, n);
121*c8917048SJakub Mazurkiewicz assert(f(3) == 5);
122*c8917048SJakub Mazurkiewicz
123*c8917048SJakub Mazurkiewicz auto g = std::bind_back(add, n, 1);
124*c8917048SJakub Mazurkiewicz assert(g() == 3);
125*c8917048SJakub Mazurkiewicz
126*c8917048SJakub Mazurkiewicz auto h = std::bind_back(add_n, 1, 1, 1);
127*c8917048SJakub Mazurkiewicz assert(h(2, 2, 2) == 9);
128*c8917048SJakub Mazurkiewicz
129*c8917048SJakub Mazurkiewicz auto i = std::bind_back(add_ref, n);
130*c8917048SJakub Mazurkiewicz std::same_as<int&> decltype(auto) iresult(i(5));
131*c8917048SJakub Mazurkiewicz assert(iresult == 7);
132*c8917048SJakub Mazurkiewicz
133*c8917048SJakub Mazurkiewicz auto j = std::bind_back(add_rref, m);
134*c8917048SJakub Mazurkiewicz std::same_as<int&&> decltype(auto) jresult(j(4));
135*c8917048SJakub Mazurkiewicz assert(jresult == 5);
136*c8917048SJakub Mazurkiewicz }
137*c8917048SJakub Mazurkiewicz }
138*c8917048SJakub Mazurkiewicz
test_edge_cases()139*c8917048SJakub Mazurkiewicz constexpr void test_edge_cases() {
140*c8917048SJakub Mazurkiewicz { // Make sure we don't treat std::reference_wrapper specially.
141*c8917048SJakub Mazurkiewicz auto sub = [](std::reference_wrapper<int> a, std::reference_wrapper<int> b) { return a.get() - b.get(); };
142*c8917048SJakub Mazurkiewicz
143*c8917048SJakub Mazurkiewicz int i = 1;
144*c8917048SJakub Mazurkiewicz int j = 2;
145*c8917048SJakub Mazurkiewicz auto f = std::bind_back(sub, std::ref(i));
146*c8917048SJakub Mazurkiewicz assert(f(std::ref(j)) == 1);
147*c8917048SJakub Mazurkiewicz }
148*c8917048SJakub Mazurkiewicz
149*c8917048SJakub Mazurkiewicz { // Make sure we can call a function that's a pointer to a member function.
150*c8917048SJakub Mazurkiewicz struct MemberFunction {
151*c8917048SJakub Mazurkiewicz constexpr int foo(int x, int y) { return x * y; }
152*c8917048SJakub Mazurkiewicz };
153*c8917048SJakub Mazurkiewicz
154*c8917048SJakub Mazurkiewicz MemberFunction value;
155*c8917048SJakub Mazurkiewicz auto fn = std::bind_back(&MemberFunction::foo, 2, 3);
156*c8917048SJakub Mazurkiewicz assert(fn(value) == 6);
157*c8917048SJakub Mazurkiewicz }
158*c8917048SJakub Mazurkiewicz
159*c8917048SJakub Mazurkiewicz { // Make sure we can call a function that's a pointer to a member object.
160*c8917048SJakub Mazurkiewicz struct MemberObject {
161*c8917048SJakub Mazurkiewicz int obj;
162*c8917048SJakub Mazurkiewicz };
163*c8917048SJakub Mazurkiewicz
164*c8917048SJakub Mazurkiewicz MemberObject value{.obj = 3};
165*c8917048SJakub Mazurkiewicz auto fn = std::bind_back(&MemberObject::obj);
166*c8917048SJakub Mazurkiewicz assert(fn(value) == 3);
167*c8917048SJakub Mazurkiewicz }
168*c8917048SJakub Mazurkiewicz }
169*c8917048SJakub Mazurkiewicz
test_passing_arguments()170*c8917048SJakub Mazurkiewicz constexpr void test_passing_arguments() {
171*c8917048SJakub Mazurkiewicz { // Make sure that we copy the bound arguments into the unspecified-type.
172*c8917048SJakub Mazurkiewicz auto add = [](int x, int y) { return x + y; };
173*c8917048SJakub Mazurkiewicz int n = 2;
174*c8917048SJakub Mazurkiewicz auto f = std::bind_back(add, n, 1);
175*c8917048SJakub Mazurkiewicz n = 100;
176*c8917048SJakub Mazurkiewicz assert(f() == 3);
177*c8917048SJakub Mazurkiewicz }
178*c8917048SJakub Mazurkiewicz
179*c8917048SJakub Mazurkiewicz { // Make sure we pass the bound arguments to the function object
180*c8917048SJakub Mazurkiewicz // with the right value category.
181*c8917048SJakub Mazurkiewicz {
182*c8917048SJakub Mazurkiewicz auto was_copied = [](CopyMoveInfo info) { return info.copy_kind == CopyMoveInfo::copy; };
183*c8917048SJakub Mazurkiewicz CopyMoveInfo info;
184*c8917048SJakub Mazurkiewicz auto f = std::bind_back(was_copied, info);
185*c8917048SJakub Mazurkiewicz assert(f());
186*c8917048SJakub Mazurkiewicz }
187*c8917048SJakub Mazurkiewicz
188*c8917048SJakub Mazurkiewicz {
189*c8917048SJakub Mazurkiewicz auto was_moved = [](CopyMoveInfo info) { return info.copy_kind == CopyMoveInfo::move; };
190*c8917048SJakub Mazurkiewicz CopyMoveInfo info;
191*c8917048SJakub Mazurkiewicz auto f = std::bind_back(was_moved, info);
192*c8917048SJakub Mazurkiewicz assert(std::move(f)());
193*c8917048SJakub Mazurkiewicz }
194*c8917048SJakub Mazurkiewicz }
195*c8917048SJakub Mazurkiewicz }
196*c8917048SJakub Mazurkiewicz
test_function_objects()197*c8917048SJakub Mazurkiewicz constexpr void test_function_objects() {
198*c8917048SJakub Mazurkiewicz { // Make sure we call the correctly cv-ref qualified operator()
199*c8917048SJakub Mazurkiewicz // based on the value category of the bind_back unspecified-type.
200*c8917048SJakub Mazurkiewicz struct X {
201*c8917048SJakub Mazurkiewicz constexpr int operator()() & { return 1; }
202*c8917048SJakub Mazurkiewicz constexpr int operator()() const& { return 2; }
203*c8917048SJakub Mazurkiewicz constexpr int operator()() && { return 3; }
204*c8917048SJakub Mazurkiewicz constexpr int operator()() const&& { return 4; }
205*c8917048SJakub Mazurkiewicz };
206*c8917048SJakub Mazurkiewicz
207*c8917048SJakub Mazurkiewicz auto f = std::bind_back(X{});
208*c8917048SJakub Mazurkiewicz using F = decltype(f);
209*c8917048SJakub Mazurkiewicz assert(static_cast<F&>(f)() == 1);
210*c8917048SJakub Mazurkiewicz assert(static_cast<const F&>(f)() == 2);
211*c8917048SJakub Mazurkiewicz assert(static_cast<F&&>(f)() == 3);
212*c8917048SJakub Mazurkiewicz assert(static_cast<const F&&>(f)() == 4);
213*c8917048SJakub Mazurkiewicz }
214*c8917048SJakub Mazurkiewicz
215*c8917048SJakub Mazurkiewicz // Make sure the `bind_back` unspecified-type does not model invocable
216*c8917048SJakub Mazurkiewicz // when the call would select a differently-qualified operator().
217*c8917048SJakub Mazurkiewicz //
218*c8917048SJakub Mazurkiewicz // For example, if the call to `operator()() &` is ill-formed, the call to the unspecified-type
219*c8917048SJakub Mazurkiewicz // should be ill-formed and not fall back to the `operator()() const&` overload.
220*c8917048SJakub Mazurkiewicz { // Make sure we delete the & overload when the underlying call isn't valid.
221*c8917048SJakub Mazurkiewicz {
222*c8917048SJakub Mazurkiewicz struct X {
223*c8917048SJakub Mazurkiewicz void operator()() & = delete;
224*c8917048SJakub Mazurkiewicz void operator()() const&;
225*c8917048SJakub Mazurkiewicz void operator()() &&;
226*c8917048SJakub Mazurkiewicz void operator()() const&&;
227*c8917048SJakub Mazurkiewicz };
228*c8917048SJakub Mazurkiewicz
229*c8917048SJakub Mazurkiewicz using F = decltype(std::bind_back(X{}));
230*c8917048SJakub Mazurkiewicz static_assert(!std::invocable<F&>);
231*c8917048SJakub Mazurkiewicz static_assert(std::invocable<const F&>);
232*c8917048SJakub Mazurkiewicz static_assert(std::invocable<F>);
233*c8917048SJakub Mazurkiewicz static_assert(std::invocable<const F>);
234*c8917048SJakub Mazurkiewicz }
235*c8917048SJakub Mazurkiewicz
236*c8917048SJakub Mazurkiewicz // There's no way to make sure we delete the const& overload when the underlying call isn't valid,
237*c8917048SJakub Mazurkiewicz // so we can't check this one.
238*c8917048SJakub Mazurkiewicz
239*c8917048SJakub Mazurkiewicz { // Make sure we delete the && overload when the underlying call isn't valid.
240*c8917048SJakub Mazurkiewicz struct X {
241*c8917048SJakub Mazurkiewicz void operator()() &;
242*c8917048SJakub Mazurkiewicz void operator()() const&;
243*c8917048SJakub Mazurkiewicz void operator()() && = delete;
244*c8917048SJakub Mazurkiewicz void operator()() const&&;
245*c8917048SJakub Mazurkiewicz };
246*c8917048SJakub Mazurkiewicz
247*c8917048SJakub Mazurkiewicz using F = decltype(std::bind_back(X{}));
248*c8917048SJakub Mazurkiewicz static_assert(std::invocable<F&>);
249*c8917048SJakub Mazurkiewicz static_assert(std::invocable<const F&>);
250*c8917048SJakub Mazurkiewicz static_assert(!std::invocable<F>);
251*c8917048SJakub Mazurkiewicz static_assert(std::invocable<const F>);
252*c8917048SJakub Mazurkiewicz }
253*c8917048SJakub Mazurkiewicz
254*c8917048SJakub Mazurkiewicz { // Make sure we delete the const&& overload when the underlying call isn't valid.
255*c8917048SJakub Mazurkiewicz struct X {
256*c8917048SJakub Mazurkiewicz void operator()() &;
257*c8917048SJakub Mazurkiewicz void operator()() const&;
258*c8917048SJakub Mazurkiewicz void operator()() &&;
259*c8917048SJakub Mazurkiewicz void operator()() const&& = delete;
260*c8917048SJakub Mazurkiewicz };
261*c8917048SJakub Mazurkiewicz
262*c8917048SJakub Mazurkiewicz using F = decltype(std::bind_back(X{}));
263*c8917048SJakub Mazurkiewicz static_assert(std::invocable<F&>);
264*c8917048SJakub Mazurkiewicz static_assert(std::invocable<const F&>);
265*c8917048SJakub Mazurkiewicz static_assert(std::invocable<F>);
266*c8917048SJakub Mazurkiewicz static_assert(!std::invocable<const F>);
267*c8917048SJakub Mazurkiewicz }
268*c8917048SJakub Mazurkiewicz }
269*c8917048SJakub Mazurkiewicz
270*c8917048SJakub Mazurkiewicz { // Extra value category tests
271*c8917048SJakub Mazurkiewicz struct X {};
272*c8917048SJakub Mazurkiewicz
273*c8917048SJakub Mazurkiewicz {
274*c8917048SJakub Mazurkiewicz struct Y {
275*c8917048SJakub Mazurkiewicz void operator()(X&&) const&;
276*c8917048SJakub Mazurkiewicz void operator()(X&&) && = delete;
277*c8917048SJakub Mazurkiewicz };
278*c8917048SJakub Mazurkiewicz
279*c8917048SJakub Mazurkiewicz using F = decltype(std::bind_back(Y{}));
280*c8917048SJakub Mazurkiewicz static_assert(std::invocable<F&, X>);
281*c8917048SJakub Mazurkiewicz static_assert(!std::invocable<F, X>);
282*c8917048SJakub Mazurkiewicz }
283*c8917048SJakub Mazurkiewicz
284*c8917048SJakub Mazurkiewicz {
285*c8917048SJakub Mazurkiewicz struct Y {
286*c8917048SJakub Mazurkiewicz void operator()(const X&) const;
287*c8917048SJakub Mazurkiewicz void operator()(X&&) const = delete;
288*c8917048SJakub Mazurkiewicz };
289*c8917048SJakub Mazurkiewicz
290*c8917048SJakub Mazurkiewicz using F = decltype(std::bind_back(Y{}, X{}));
291*c8917048SJakub Mazurkiewicz static_assert(std::invocable<F&>);
292*c8917048SJakub Mazurkiewicz static_assert(!std::invocable<F>);
293*c8917048SJakub Mazurkiewicz }
294*c8917048SJakub Mazurkiewicz }
295*c8917048SJakub Mazurkiewicz }
296*c8917048SJakub Mazurkiewicz
test_return_type()297*c8917048SJakub Mazurkiewicz constexpr void test_return_type() {
298*c8917048SJakub Mazurkiewicz { // Test properties of the constructor of the unspecified-type returned by bind_back.
299*c8917048SJakub Mazurkiewicz { // Test move constructor when function is move only.
300*c8917048SJakub Mazurkiewicz MoveOnlyCallable<bool> value(true);
301*c8917048SJakub Mazurkiewicz auto f = std::bind_back(std::move(value), 1);
302*c8917048SJakub Mazurkiewicz assert(f());
303*c8917048SJakub Mazurkiewicz assert(f(1, 2, 3));
304*c8917048SJakub Mazurkiewicz
305*c8917048SJakub Mazurkiewicz auto f1 = std::move(f);
306*c8917048SJakub Mazurkiewicz assert(!f());
307*c8917048SJakub Mazurkiewicz assert(f1());
308*c8917048SJakub Mazurkiewicz assert(f1(1, 2, 3));
309*c8917048SJakub Mazurkiewicz
310*c8917048SJakub Mazurkiewicz using F = decltype(f);
311*c8917048SJakub Mazurkiewicz static_assert(std::is_move_constructible<F>::value);
312*c8917048SJakub Mazurkiewicz static_assert(!std::is_copy_constructible<F>::value);
313*c8917048SJakub Mazurkiewicz static_assert(!std::is_move_assignable<F>::value);
314*c8917048SJakub Mazurkiewicz static_assert(!std::is_copy_assignable<F>::value);
315*c8917048SJakub Mazurkiewicz }
316*c8917048SJakub Mazurkiewicz
317*c8917048SJakub Mazurkiewicz { // Test move constructor when function is copyable but not assignable.
318*c8917048SJakub Mazurkiewicz CopyCallable<bool> value(true);
319*c8917048SJakub Mazurkiewicz auto f = std::bind_back(value, 1);
320*c8917048SJakub Mazurkiewicz assert(f());
321*c8917048SJakub Mazurkiewicz assert(f(1, 2, 3));
322*c8917048SJakub Mazurkiewicz
323*c8917048SJakub Mazurkiewicz auto f1 = std::move(f);
324*c8917048SJakub Mazurkiewicz assert(!f());
325*c8917048SJakub Mazurkiewicz assert(f1());
326*c8917048SJakub Mazurkiewicz assert(f1(1, 2, 3));
327*c8917048SJakub Mazurkiewicz
328*c8917048SJakub Mazurkiewicz auto f2 = std::bind_back(std::move(value), 1);
329*c8917048SJakub Mazurkiewicz assert(f1());
330*c8917048SJakub Mazurkiewicz assert(f2());
331*c8917048SJakub Mazurkiewicz assert(f2(1, 2, 3));
332*c8917048SJakub Mazurkiewicz
333*c8917048SJakub Mazurkiewicz using F = decltype(f);
334*c8917048SJakub Mazurkiewicz static_assert(std::is_move_constructible<F>::value);
335*c8917048SJakub Mazurkiewicz static_assert(std::is_copy_constructible<F>::value);
336*c8917048SJakub Mazurkiewicz static_assert(!std::is_move_assignable<F>::value);
337*c8917048SJakub Mazurkiewicz static_assert(!std::is_copy_assignable<F>::value);
338*c8917048SJakub Mazurkiewicz }
339*c8917048SJakub Mazurkiewicz
340*c8917048SJakub Mazurkiewicz { // Test constructors when function is copy assignable.
341*c8917048SJakub Mazurkiewicz using F = decltype(std::bind_back(std::declval<CopyAssignableWrapper&>(), 1));
342*c8917048SJakub Mazurkiewicz static_assert(std::is_move_constructible<F>::value);
343*c8917048SJakub Mazurkiewicz static_assert(std::is_copy_constructible<F>::value);
344*c8917048SJakub Mazurkiewicz static_assert(std::is_move_assignable<F>::value);
345*c8917048SJakub Mazurkiewicz static_assert(std::is_copy_assignable<F>::value);
346*c8917048SJakub Mazurkiewicz }
347*c8917048SJakub Mazurkiewicz
348*c8917048SJakub Mazurkiewicz { // Test constructors when function is move assignable only.
349*c8917048SJakub Mazurkiewicz using F = decltype(std::bind_back(std::declval<MoveAssignableWrapper>(), 1));
350*c8917048SJakub Mazurkiewicz static_assert(std::is_move_constructible<F>::value);
351*c8917048SJakub Mazurkiewicz static_assert(!std::is_copy_constructible<F>::value);
352*c8917048SJakub Mazurkiewicz static_assert(std::is_move_assignable<F>::value);
353*c8917048SJakub Mazurkiewicz static_assert(!std::is_copy_assignable<F>::value);
354*c8917048SJakub Mazurkiewicz }
355*c8917048SJakub Mazurkiewicz }
356*c8917048SJakub Mazurkiewicz
357*c8917048SJakub Mazurkiewicz { // Make sure bind_back's unspecified type's operator() is SFINAE-friendly.
358*c8917048SJakub Mazurkiewicz using F = decltype(std::bind_back(std::declval<int (*)(int, int)>(), 1));
359*c8917048SJakub Mazurkiewicz static_assert(!std::is_invocable<F>::value);
360*c8917048SJakub Mazurkiewicz static_assert(std::is_invocable<F, int>::value);
361*c8917048SJakub Mazurkiewicz static_assert(!std::is_invocable<F, void*>::value);
362*c8917048SJakub Mazurkiewicz static_assert(!std::is_invocable<F, int, int>::value);
363*c8917048SJakub Mazurkiewicz }
364*c8917048SJakub Mazurkiewicz }
365*c8917048SJakub Mazurkiewicz
test()366*c8917048SJakub Mazurkiewicz constexpr bool test() {
367*c8917048SJakub Mazurkiewicz test_basic_bindings();
368*c8917048SJakub Mazurkiewicz test_edge_cases();
369*c8917048SJakub Mazurkiewicz test_passing_arguments();
370*c8917048SJakub Mazurkiewicz test_function_objects();
371*c8917048SJakub Mazurkiewicz test_return_type();
372*c8917048SJakub Mazurkiewicz
373*c8917048SJakub Mazurkiewicz return true;
374*c8917048SJakub Mazurkiewicz }
375*c8917048SJakub Mazurkiewicz
main(int,char **)376*c8917048SJakub Mazurkiewicz int main(int, char**) {
377*c8917048SJakub Mazurkiewicz test();
378*c8917048SJakub Mazurkiewicz static_assert(test());
379*c8917048SJakub Mazurkiewicz
380*c8917048SJakub Mazurkiewicz return 0;
381*c8917048SJakub Mazurkiewicz }
382