]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/20_util/function_objects/bind_front/1.cc
aa7f240b30eb54f710f50c64a62508bb3d0fb0fb
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / 20_util / function_objects / bind_front / 1.cc
1 // Copyright (C) 2014-2022 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
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
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
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
151 int f(int i, int j, int k) { return i + j + k; }
152
153 void
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
170 main()
171 {
172 test01();
173 test02();
174 test03();
175 test04();
176 }