]>
git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/20_util/function_objects/bind_front/1.cc
1 // Copyright (C) 2014-2024 Free Software Foundation, Inc.
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)
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.
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/>.
18 // { dg-do run { target c++20 } }
19 // { dg-add-options no_pch }
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>"
29 #include <testsuite_hooks.h>
31 using std::bind_front
;
33 using std::is_invocable_v
;
34 using std::is_invocable_r_v
;
39 struct F
{ void operator()() {} };
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&>()))
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&>()))
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&>())))
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&>())))
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&>())))
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 }; }
84 auto g
= bind_front(f
);
88 // constness and value category should be forwarded to the target object:
90 VERIFY( ! q
.as_const
&& q
.as_lvalue
);
92 VERIFY( ! q
.as_const
&& ! q
.as_lvalue
);
94 VERIFY( q
.as_const
&& q
.as_lvalue
);
96 VERIFY( q
.as_const
&& ! q
.as_lvalue
);
104 int& operator()(int& i
, void*) { return i
; }
105 void* operator()(int, void* p
) const { return p
; }
109 void* vp
= &vp
; // arbitrary void* value
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
);
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*>);
131 int& i2r
= static_cast<G2
&&>(g2
)(vp
);
132 VERIFY( &i2r
== &i
);
133 void* p2
= const_cast<const G2
&>(g2
)(vp
);
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*>);
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
&&>);
152 int f(int i
, int j
, int k
) { return i
+ j
+ k
; }
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);
167 VERIFY( bind_front(g2
, 3)() == 6 );