]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/20_util/function_objects/bind_front/1.cc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / 20_util / function_objects / bind_front / 1.cc
1 // Copyright (C) 2014-2024 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-do run { target c++20 } }
19 // { dg-add-options no_pch }
20
21 #include <functional>
22
23 #ifndef __cpp_lib_bind_front
24 # error "Feature test macro for bind_front is missing in <functional>"
25 #elif __cpp_lib_bind_front < 201902L
26 # error "Feature test macro for bind_front has wrong value in <functional>"
27 #endif
28
29 #include <testsuite_hooks.h>
30
31 using std::bind_front;
32 using std::is_same_v;
33 using std::is_invocable_v;
34 using std::is_invocable_r_v;
35
36 void
37 test01()
38 {
39 struct F { void operator()() {} };
40
41 // Arguments should be decayed:
42 static_assert(std::is_same_v<
43 decltype(bind_front(std::declval<F>(), std::declval<int>())),
44 decltype(bind_front(std::declval<F&>(), std::declval<int&>()))
45 >);
46 static_assert(std::is_same_v<
47 decltype(bind_front(std::declval<F>(), std::declval<int>())),
48 decltype(bind_front(std::declval<const F&>(), std::declval<const int&>()))
49 >);
50
51 // Reference wrappers should be handled:
52 static_assert(!std::is_same_v<
53 decltype(bind_front(std::declval<F>(), std::declval<int&>())),
54 decltype(bind_front(std::declval<F>(), std::ref(std::declval<int&>())))
55 >);
56 static_assert(!std::is_same_v<
57 decltype(bind_front(std::declval<F>(), std::declval<const int&>())),
58 decltype(bind_front(std::declval<F>(), std::cref(std::declval<int&>())))
59 >);
60 static_assert(!std::is_same_v<
61 decltype(bind_front(std::declval<F>(), std::ref(std::declval<int&>()))),
62 decltype(bind_front(std::declval<F>(), std::cref(std::declval<int&>())))
63 >);
64 }
65
66 void
67 test02()
68 {
69 struct quals
70 {
71 bool as_const;
72 bool as_lvalue;
73 };
74
75 struct F
76 {
77 quals operator()() & { return { false, true }; }
78 quals operator()() const & { return { true, true }; }
79 quals operator()() && { return { false, false }; }
80 quals operator()() const && { return { true, false }; }
81 };
82
83 F f;
84 auto g = bind_front(f);
85 const auto& cg = g;
86 quals q;
87
88 // constness and value category should be forwarded to the target object:
89 q = g();
90 VERIFY( ! q.as_const && q.as_lvalue );
91 q = std::move(g)();
92 VERIFY( ! q.as_const && ! q.as_lvalue );
93 q = cg();
94 VERIFY( q.as_const && q.as_lvalue );
95 q = std::move(cg)();
96 VERIFY( q.as_const && ! q.as_lvalue );
97 }
98
99 void
100 test03()
101 {
102 struct F
103 {
104 int& operator()(int& i, void*) { return i; }
105 void* operator()(int, void* p) const { return p; }
106 };
107
108 int i = 5;
109 void* vp = &vp; // arbitrary void* value
110
111 auto g1 = bind_front(F{}, i); // call wrapper has bound arg of type int
112 using G1 = decltype(g1);
113 // Invoking G1& will pass g1's bound arg as int&, so calls first overload:
114 static_assert(is_invocable_r_v<int&, G1&, void*>);
115 // Invoking const G1& or G&& calls second overload:
116 static_assert(is_invocable_r_v<void*, const G1&, void*>);
117 static_assert(is_invocable_r_v<void*, G1&&, void*>);
118 void* p1 = static_cast<G1&&>(g1)(vp);
119 VERIFY( p1 == vp );
120
121 auto g2 = bind_front(F{}, std::ref(i)); // bound arg of type int&
122 using G2 = decltype(g2);
123 // Bound arg always forwarded as int& even from G2&& or const G2&
124 static_assert(is_invocable_r_v<int&, G2&, void*>);
125 static_assert(is_invocable_r_v<int&, G2&&, void*>);
126 // But cannot call first overload on const G2:
127 static_assert(is_invocable_r_v<void*, const G2&, void*>);
128 static_assert(is_invocable_r_v<void*, const G2&&, void*>);
129 int& i2 = g2(vp);
130 VERIFY( &i2 == &i );
131 int& i2r = static_cast<G2&&>(g2)(vp);
132 VERIFY( &i2r == &i );
133 void* p2 = const_cast<const G2&>(g2)(vp);
134 VERIFY( p2 == vp );
135
136 auto g3 = bind_front(F{}, std::cref(i)); // bound arg of type const int&
137 using G3 = decltype(g3);
138 // Bound arg always forwarded as const int& so can only call second overload:
139 static_assert(is_invocable_r_v<void*, G3&, void*>);
140 static_assert(is_invocable_r_v<void*, G3&&, void*>);
141 static_assert(is_invocable_r_v<void*, const G3&, void*>);
142 static_assert(is_invocable_r_v<void*, const G3&&, void*>);
143
144 auto g4 = bind_front(g2, nullptr);
145 using G4 = decltype(g4);
146 static_assert(is_invocable_r_v<int&, G4&>);
147 static_assert(is_invocable_r_v<int&, G4&&>);
148 static_assert(is_invocable_r_v<void*, const G4&>);
149 static_assert(is_invocable_r_v<void*, const G4&&>);
150 }
151
152 int f(int i, int j, int k) { return i + j + k; }
153
154 void
155 test04()
156 {
157 auto g = bind_front(f);
158 VERIFY( g(1, 2, 3) == 6 );
159 auto g1 = bind_front(f, 1);
160 VERIFY( g1(2, 3) == 6 );
161 VERIFY( bind_front(g, 1)(2, 3) == 6 );
162 auto g2 = bind_front(f, 1, 2);
163 VERIFY( g2(3) == 6 );
164 VERIFY( bind_front(g1, 2)(3) == 6 );
165 auto g3 = bind_front(f, 1, 2, 3);
166 VERIFY( g3() == 6 );
167 VERIFY( bind_front(g2, 3)() == 6 );
168 }
169
170 int
171 main()
172 {
173 test01();
174 test02();
175 test03();
176 test04();
177 }