]>
git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/20_util/function_objects/bind_front/1.cc
1 // Copyright (C) 2014-2019 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-options "-std=gnu++2a" }
19 // { dg-do run { target c++2a } }
22 #include <testsuite_hooks.h>
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"
30 using std::bind_front
;
32 using std::is_invocable_v
;
33 using std::is_invocable_r_v
;
38 struct F
{ void operator()() {} };
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&>()))
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&>()))
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&>())))
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&>())))
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&>())))
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 }; }
83 auto g
= bind_front(f
);
87 // constness and value category should be forwarded to the target object:
89 VERIFY( ! q
.as_const
&& q
.as_lvalue
);
91 VERIFY( ! q
.as_const
&& ! q
.as_lvalue
);
93 VERIFY( q
.as_const
&& q
.as_lvalue
);
95 VERIFY( q
.as_const
&& ! q
.as_lvalue
);
103 int& operator()(int& i
, void*) { return i
; }
104 void* operator()(int, void* p
) const { return p
; }
108 void* vp
= &vp
; // arbitrary void* value
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
);
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*>);
130 int& i2r
= static_cast<G2
&&>(g2
)(vp
);
131 VERIFY( &i2r
== &i
);
132 void* p2
= const_cast<const G2
&>(g2
)(vp
);
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*>);
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
&&>);
151 int f(int i
, int j
, int k
) { return i
+ j
+ k
; }
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);
166 VERIFY( bind_front(g2
, 3)() == 6 );