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 // UNSUPPORTED: c++03
10
11 // <functional>
12
13 // template<CopyConstructible Fn, CopyConstructible... Types>
14 // unspecified bind(Fn, Types...);
15 // template<Returnable R, CopyConstructible Fn, CopyConstructible... Types>
16 // unspecified bind(Fn, Types...);
17
18 // Check that the call operators have the proper return type and that they
19 // only SFINAE away when too few arguments are provided. Otherwise they should
20 // be well formed and should ignore any additional arguments.
21
22 #include <functional>
23 #include <type_traits>
24 #include <cassert>
25
26 #include "test_macros.h"
27
28 int dummy = 42;
29
return_value(int)30 int return_value(int) { return dummy; }
return_lvalue(int)31 int& return_lvalue(int) { return dummy; }
return_const_lvalue(int)32 const int& return_const_lvalue(int) { return dummy; }
return_rvalue(int)33 int&& return_rvalue(int) { return std::move(dummy); }
return_const_rvalue(int)34 const int&& return_const_rvalue(int) { return std::move(dummy); }
35
36 template <class Bind, class ...Args>
37 auto CheckCallImp(int)
38 -> decltype((std::declval<Bind>()(std::declval<Args>()...)), std::true_type{});
39
40 template <class Bind, class ...>
41 auto CheckCallImp(long) -> std::false_type;
42
43 template <class ...Args>
CheckCall()44 constexpr bool CheckCall() {
45 return decltype(CheckCallImp<Args...>(0))::value;
46 }
47
48 template <class Expect, class Fn>
do_test(Fn * func)49 void do_test(Fn* func) {
50 using namespace std::placeholders;
51 auto ret = std::bind(func, _1);
52 auto ret_r = std::bind<Expect>(func, _1);
53 using Bind = decltype(ret);
54 using BindR = decltype(ret_r);
55
56 using Ret = decltype(ret(42));
57 using Ret2 = decltype(ret(42, 43)); // Test that the extra argument is discarded.
58 using RetR = decltype(ret_r(42));
59 using RetR2 = decltype(ret_r(42, 43));
60
61 static_assert(std::is_same<Ret, Expect>::value, "");
62 static_assert(std::is_same<Ret2, Expect>::value, "");
63 static_assert(std::is_same<RetR, Expect>::value, "");
64 static_assert(std::is_same<RetR2, Expect>::value, "");
65
66 Expect exp = ret(100); // the input value is ignored. dummy is returned.
67 Expect exp2 = ret(101, 102);
68 Expect exp_r = ret_r(100);
69 Expect exp_r2 = ret_r(101, 102);
70
71 assert(exp == 42);
72 assert(exp2 == 42);
73 assert(exp_r == 42);
74 assert(exp_r2 == 42);
75
76 if ((std::is_reference<Expect>::value)) {
77 assert(&exp == &dummy);
78 assert(&exp2 == &dummy);
79 assert(&exp_r == &dummy);
80 assert(&exp_r2 == &dummy);
81 }
82 // Check that the call operator SFINAE's away when too few arguments
83 // are provided but is well-formed otherwise.
84 {
85 LIBCPP_STATIC_ASSERT(!CheckCall<Bind>(), "");
86 static_assert(CheckCall<Bind, int>(), "");
87 static_assert(CheckCall<Bind, int, int>(), "");
88 LIBCPP_STATIC_ASSERT(!CheckCall<BindR>(), "");
89 static_assert(CheckCall<BindR, int>(), "");
90 static_assert(CheckCall<BindR, int, int>(), "");
91 }
92 }
93
94
95 // Test but with an explicit return type which differs from the real one.
96 template <class Expect, class Fn>
do_test_r(Fn * func)97 void do_test_r(Fn* func) {
98 using namespace std::placeholders;
99 auto ret = std::bind<Expect>(func, _1);
100 using Bind = decltype(ret);
101 using Ret = decltype(ret(42));
102 using Ret2 = decltype(ret(42, 43)); // Test that the extra argument is discarded.
103 static_assert(std::is_same<Ret, Expect>::value, "");
104 static_assert(std::is_same<Ret2, Expect>::value, "");
105 Expect exp = ret(100); // the input value is ignored
106 Expect exp2 = ret(101, 102);
107 assert(exp == 42);
108 assert(exp2 == 42);
109 // Check that the call operator SFINAE's away when too few arguments
110 // are provided but is well-formed otherwise.
111 {
112 LIBCPP_STATIC_ASSERT(!CheckCall<Bind>(), "");
113 static_assert(CheckCall<Bind, int>(), "");
114 static_assert(CheckCall<Bind, int, int>(), "");
115 }
116 }
117
main(int,char **)118 int main(int, char**)
119 {
120 do_test<int>(return_value);
121 do_test<int&>(return_lvalue);
122 do_test<const int&>(return_const_lvalue);
123 do_test<int&&>(return_rvalue);
124 do_test<const int&&>(return_const_rvalue);
125
126 do_test_r<long>(return_value);
127 do_test_r<long>(return_lvalue);
128 do_test_r<long>(return_const_lvalue);
129 do_test_r<long>(return_rvalue);
130 do_test_r<long>(return_const_rvalue);
131
132
133 return 0;
134 }
135