1 // Copyright (C) 2014-2021 Free Software Foundation, Inc.
2 //
3 // This file is part of the GNU ISO C++ Library.  This library is free
4 // software; you can redistribute it and/or modify it under the
5 // terms of the GNU General Public License as published by the
6 // Free Software Foundation; either version 3, or (at your option)
7 // any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 
14 // You should have received a copy of the GNU General Public License along
15 // with this library; see the file COPYING3.  If not see
16 // <http://www.gnu.org/licenses/>.
17 
18 // { dg-options "-std=gnu++2a" }
19 // { dg-do run { target c++2a } }
20 
21 #include <functional>
22 #include <testsuite_hooks.h>
23 
24 #ifndef __cpp_lib_bind_front
25 # error "Feature test macro for bind_front is missing"
26 #elif __cpp_lib_bind_front < 201902L
27 # error "Feature test macro for bind_front has wrong value"
28 #endif
29 
30 using std::bind_front;
31 using std::is_same_v;
32 using std::is_invocable_v;
33 using std::is_invocable_r_v;
34 
35 void
test01()36 test01()
37 {
38   struct F { void operator()() {} };
39 
40   // Arguments should be decayed:
41   static_assert(std::is_same_v<
42       decltype(bind_front(std::declval<F>(), std::declval<int>())),
43       decltype(bind_front(std::declval<F&>(), std::declval<int&>()))
44       >);
45   static_assert(std::is_same_v<
46       decltype(bind_front(std::declval<F>(), std::declval<int>())),
47       decltype(bind_front(std::declval<const F&>(), std::declval<const int&>()))
48       >);
49 
50   // Reference wrappers should be handled:
51   static_assert(!std::is_same_v<
52       decltype(bind_front(std::declval<F>(), std::declval<int&>())),
53       decltype(bind_front(std::declval<F>(), std::ref(std::declval<int&>())))
54       >);
55   static_assert(!std::is_same_v<
56       decltype(bind_front(std::declval<F>(), std::declval<const int&>())),
57       decltype(bind_front(std::declval<F>(), std::cref(std::declval<int&>())))
58       >);
59   static_assert(!std::is_same_v<
60       decltype(bind_front(std::declval<F>(), std::ref(std::declval<int&>()))),
61       decltype(bind_front(std::declval<F>(), std::cref(std::declval<int&>())))
62       >);
63 }
64 
65 void
test02()66 test02()
67 {
68   struct quals
69   {
70     bool as_const;
71     bool as_lvalue;
72   };
73 
74   struct F
75   {
76     quals operator()() & { return { false, true }; }
77     quals operator()() const & { return { true, true }; }
78     quals operator()() && { return { false, false }; }
79     quals operator()() const && { return { true, false }; }
80   };
81 
82   F f;
83   auto g = bind_front(f);
84   const auto& cg = g;
85   quals q;
86 
87   // constness and value category should be forwarded to the target object:
88   q = g();
89   VERIFY( ! q.as_const && q.as_lvalue );
90   q = std::move(g)();
91   VERIFY( ! q.as_const && ! q.as_lvalue );
92   q = cg();
93   VERIFY( q.as_const && q.as_lvalue );
94   q = std::move(cg)();
95   VERIFY( q.as_const && ! q.as_lvalue );
96 }
97 
98 void
test03()99 test03()
100 {
101   struct F
102   {
103     int& operator()(int& i, void*) { return i; }
104     void* operator()(int, void* p) const { return p; }
105   };
106 
107   int i = 5;
108   void* vp = &vp; // arbitrary void* value
109 
110   auto g1 = bind_front(F{}, i); // call wrapper has bound arg of type int
111   using G1 = decltype(g1);
112   // Invoking G1& will pass g1's bound arg as int&, so calls first overload:
113   static_assert(is_invocable_r_v<int&, G1&, void*>);
114   // Invoking const G1& or G&& calls second overload:
115   static_assert(is_invocable_r_v<void*, const G1&, void*>);
116   static_assert(is_invocable_r_v<void*, G1&&, void*>);
117   void* p1 = static_cast<G1&&>(g1)(vp);
118   VERIFY( p1 == vp );
119 
120   auto g2 = bind_front(F{}, std::ref(i)); // bound arg of type int&
121   using G2 = decltype(g2);
122   // Bound arg always forwarded as int& even from G2&& or const G2&
123   static_assert(is_invocable_r_v<int&, G2&, void*>);
124   static_assert(is_invocable_r_v<int&, G2&&, void*>);
125   // But cannot call first overload on const G2:
126   static_assert(is_invocable_r_v<void*, const G2&, void*>);
127   static_assert(is_invocable_r_v<void*, const G2&&, void*>);
128   int& i2 = g2(vp);
129   VERIFY( &i2 == &i );
130   int& i2r = static_cast<G2&&>(g2)(vp);
131   VERIFY( &i2r == &i );
132   void* p2 = const_cast<const G2&>(g2)(vp);
133   VERIFY( p2 == vp );
134 
135   auto g3 = bind_front(F{}, std::cref(i)); // bound arg of type const int&
136   using G3 = decltype(g3);
137   // Bound arg always forwarded as const int& so can only call second overload:
138   static_assert(is_invocable_r_v<void*, G3&, void*>);
139   static_assert(is_invocable_r_v<void*, G3&&, void*>);
140   static_assert(is_invocable_r_v<void*, const G3&, void*>);
141   static_assert(is_invocable_r_v<void*, const G3&&, void*>);
142 
143   auto g4 = bind_front(g2, nullptr);
144   using G4 = decltype(g4);
145   static_assert(is_invocable_r_v<int&, G4&>);
146   static_assert(is_invocable_r_v<int&, G4&&>);
147   static_assert(is_invocable_r_v<void*, const G4&>);
148   static_assert(is_invocable_r_v<void*, const G4&&>);
149 }
150 
f(int i,int j,int k)151 int f(int i, int j, int k) { return i + j + k; }
152 
153 void
test04()154 test04()
155 {
156   auto g = bind_front(f);
157   VERIFY( g(1, 2, 3) == 6 );
158   auto g1 = bind_front(f, 1);
159   VERIFY( g1(2, 3) == 6 );
160   VERIFY( bind_front(g, 1)(2, 3) == 6 );
161   auto g2 = bind_front(f, 1, 2);
162   VERIFY( g2(3) == 6 );
163   VERIFY( bind_front(g1, 2)(3) == 6 );
164   auto g3 = bind_front(f, 1, 2, 3);
165   VERIFY( g3() == 6 );
166   VERIFY( bind_front(g2, 3)() == 6 );
167 }
168 
169 int
main()170 main()
171 {
172   test01();
173   test02();
174   test03();
175   test04();
176 }
177