1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14, c++17
13 // template <class F, class... Args>
14 // constexpr unspecified bind_front(F&&, Args&&...);
19 #include <type_traits>
22 #include "callable_types.h"
23 #include "test_macros.h"
26 enum { none
, copy
, move
} copy_kind
;
28 constexpr CopyMoveInfo() : copy_kind(none
) {}
29 constexpr CopyMoveInfo(CopyMoveInfo
const&) : copy_kind(copy
) {}
30 constexpr CopyMoveInfo(CopyMoveInfo
&&) : copy_kind(move
) {}
33 template <class ...Args
>
34 struct is_bind_frontable
{
35 template <class ...LocalArgs
>
37 -> decltype((void)std::bind_front(std::declval
<LocalArgs
>()...), std::true_type());
40 static std::false_type
test(...);
42 static constexpr bool value
= decltype(test
<Args
...>(0))::value
;
46 NotCopyMove() = delete;
47 NotCopyMove(const NotCopyMove
&) = delete;
48 NotCopyMove(NotCopyMove
&&) = delete;
49 template <class ...Args
>
50 void operator()(Args
&& ...) const { }
53 struct NonConstCopyConstructible
{
54 explicit NonConstCopyConstructible() {}
55 NonConstCopyConstructible(NonConstCopyConstructible
&) {}
58 struct MoveConstructible
{
59 explicit MoveConstructible() {}
60 MoveConstructible(MoveConstructible
&&) {}
64 template <class ...Args
>
65 constexpr auto operator()(Args
&& ...args
) const {
66 return std::make_tuple(std::forward
<Args
>(args
)...);
73 constexpr bool operator==(Elem
<Y
> const&) const
77 constexpr bool test() {
78 // Bind arguments, call without arguments
81 auto f
= std::bind_front(MakeTuple
{});
82 assert(f() == std::make_tuple());
85 auto f
= std::bind_front(MakeTuple
{}, Elem
<1>{});
86 assert(f() == std::make_tuple(Elem
<1>{}));
89 auto f
= std::bind_front(MakeTuple
{}, Elem
<1>{}, Elem
<2>{});
90 assert(f() == std::make_tuple(Elem
<1>{}, Elem
<2>{}));
93 auto f
= std::bind_front(MakeTuple
{}, Elem
<1>{}, Elem
<2>{}, Elem
<3>{});
94 assert(f() == std::make_tuple(Elem
<1>{}, Elem
<2>{}, Elem
<3>{}));
98 // Bind no arguments, call with arguments
101 auto f
= std::bind_front(MakeTuple
{});
102 assert(f(Elem
<1>{}) == std::make_tuple(Elem
<1>{}));
105 auto f
= std::bind_front(MakeTuple
{});
106 assert(f(Elem
<1>{}, Elem
<2>{}) == std::make_tuple(Elem
<1>{}, Elem
<2>{}));
109 auto f
= std::bind_front(MakeTuple
{});
110 assert(f(Elem
<1>{}, Elem
<2>{}, Elem
<3>{}) == std::make_tuple(Elem
<1>{}, Elem
<2>{}, Elem
<3>{}));
114 // Bind arguments, call with arguments
117 auto f
= std::bind_front(MakeTuple
{}, Elem
<1>{});
118 assert(f(Elem
<10>{}) == std::make_tuple(Elem
<1>{}, Elem
<10>{}));
121 auto f
= std::bind_front(MakeTuple
{}, Elem
<1>{}, Elem
<2>{});
122 assert(f(Elem
<10>{}) == std::make_tuple(Elem
<1>{}, Elem
<2>{}, Elem
<10>{}));
125 auto f
= std::bind_front(MakeTuple
{}, Elem
<1>{}, Elem
<2>{}, Elem
<3>{});
126 assert(f(Elem
<10>{}) == std::make_tuple(Elem
<1>{}, Elem
<2>{}, Elem
<3>{}, Elem
<10>{}));
130 auto f
= std::bind_front(MakeTuple
{}, Elem
<1>{});
131 assert(f(Elem
<10>{}, Elem
<11>{}) == std::make_tuple(Elem
<1>{}, Elem
<10>{}, Elem
<11>{}));
134 auto f
= std::bind_front(MakeTuple
{}, Elem
<1>{}, Elem
<2>{});
135 assert(f(Elem
<10>{}, Elem
<11>{}) == std::make_tuple(Elem
<1>{}, Elem
<2>{}, Elem
<10>{}, Elem
<11>{}));
138 auto f
= std::bind_front(MakeTuple
{}, Elem
<1>{}, Elem
<2>{}, Elem
<3>{});
139 assert(f(Elem
<10>{}, Elem
<11>{}) == std::make_tuple(Elem
<1>{}, Elem
<2>{}, Elem
<3>{}, Elem
<10>{}, Elem
<11>{}));
143 // Basic tests with fundamental types
147 auto add
= [](int x
, int y
) { return x
+ y
; };
148 auto addN
= [](int a
, int b
, int c
, int d
, int e
, int f
) {
149 return a
+ b
+ c
+ d
+ e
+ f
;
152 auto a
= std::bind_front(add
, m
, n
);
155 auto b
= std::bind_front(addN
, m
, n
, m
, m
, m
, m
);
158 auto c
= std::bind_front(addN
, n
, m
);
159 assert(c(1, 1, 1, 1) == 7);
161 auto f
= std::bind_front(add
, n
);
164 auto g
= std::bind_front(add
, n
, 1);
167 auto h
= std::bind_front(addN
, 1, 1, 1);
168 assert(h(2, 2, 2) == 9);
171 // Make sure we don't treat std::reference_wrapper specially.
173 auto add
= [](std::reference_wrapper
<int> a
, std::reference_wrapper
<int> b
) {
174 return a
.get() + b
.get();
177 auto f
= std::bind_front(add
, std::ref(i
));
178 assert(f(std::ref(j
)) == 3);
181 // Make sure we can call a function that's a pointer to a member function.
183 struct MemberFunction
{
184 constexpr bool foo(int, int) { return true; }
186 MemberFunction value
;
187 auto fn
= std::bind_front(&MemberFunction::foo
, value
, 0);
191 // Make sure that we copy the bound arguments into the unspecified-type.
193 auto add
= [](int x
, int y
) { return x
+ y
; };
195 auto i
= std::bind_front(add
, n
, 1);
200 // Make sure we pass the bound arguments to the function object
201 // with the right value category.
204 auto wasCopied
= [](CopyMoveInfo info
) {
205 return info
.copy_kind
== CopyMoveInfo::copy
;
208 auto copied
= std::bind_front(wasCopied
, info
);
213 auto wasMoved
= [](CopyMoveInfo info
) {
214 return info
.copy_kind
== CopyMoveInfo::move
;
217 auto moved
= std::bind_front(wasMoved
, info
);
218 assert(std::move(moved
)());
222 // Make sure we call the correctly cv-ref qualified operator() based on the
223 // value category of the bind_front unspecified-type.
226 constexpr int operator()() & { return 1; }
227 constexpr int operator()() const& { return 2; }
228 constexpr int operator()() && { return 3; }
229 constexpr int operator()() const&& { return 4; }
231 auto x
= std::bind_front(F
{});
232 using X
= decltype(x
);
233 assert(static_cast<X
&>(x
)() == 1);
234 assert(static_cast<X
const&>(x
)() == 2);
235 assert(static_cast<X
&&>(x
)() == 3);
236 assert(static_cast<X
const&&>(x
)() == 4);
239 // Make sure the bind_front unspecified-type is NOT invocable when the call would select a
240 // differently-qualified operator().
242 // For example, if the call to `operator()() &` is ill-formed, the call to the unspecified-type
243 // should be ill-formed and not fall back to the `operator()() const&` overload.
245 // Make sure we delete the & overload when the underlying call isn't valid
248 void operator()() & = delete;
249 void operator()() const&;
250 void operator()() &&;
251 void operator()() const&&;
253 using X
= decltype(std::bind_front(F
{}));
254 static_assert(!std::is_invocable_v
<X
&>);
255 static_assert( std::is_invocable_v
<X
const&>);
256 static_assert( std::is_invocable_v
<X
>);
257 static_assert( std::is_invocable_v
<X
const>);
260 // There's no way to make sure we delete the const& overload when the underlying call isn't valid,
261 // so we can't check this one.
263 // Make sure we delete the && overload when the underlying call isn't valid
267 void operator()() const&;
268 void operator()() && = delete;
269 void operator()() const&&;
271 using X
= decltype(std::bind_front(F
{}));
272 static_assert( std::is_invocable_v
<X
&>);
273 static_assert( std::is_invocable_v
<X
const&>);
274 static_assert(!std::is_invocable_v
<X
>);
275 static_assert( std::is_invocable_v
<X
const>);
278 // Make sure we delete the const&& overload when the underlying call isn't valid
282 void operator()() const&;
283 void operator()() &&;
284 void operator()() const&& = delete;
286 using X
= decltype(std::bind_front(F
{}));
287 static_assert( std::is_invocable_v
<X
&>);
288 static_assert( std::is_invocable_v
<X
const&>);
289 static_assert( std::is_invocable_v
<X
>);
290 static_assert(!std::is_invocable_v
<X
const>);
294 // Some examples by Tim Song
299 void operator()(T
&&) const &;
300 void operator()(T
&&) && = delete;
302 using X
= decltype(std::bind_front(F
{}));
303 static_assert(!std::is_invocable_v
<X
, T
>);
309 void operator()(T
const&) const;
310 void operator()(T
&&) const = delete;
312 using X
= decltype(std::bind_front(F
{}, T
{}));
313 static_assert(!std::is_invocable_v
<X
>);
317 // Test properties of the constructor of the unspecified-type returned by bind_front.
320 MoveOnlyCallable
<bool> value(true);
321 auto ret
= std::bind_front(std::move(value
), 1);
323 assert(ret(1, 2, 3));
325 auto ret1
= std::move(ret
);
328 assert(ret1(1, 2, 3));
330 using RetT
= decltype(ret
);
331 static_assert( std::is_move_constructible
<RetT
>::value
);
332 static_assert(!std::is_copy_constructible
<RetT
>::value
);
333 static_assert(!std::is_move_assignable
<RetT
>::value
);
334 static_assert(!std::is_copy_assignable
<RetT
>::value
);
337 CopyCallable
<bool> value(true);
338 auto ret
= std::bind_front(value
, 1);
340 assert(ret(1, 2, 3));
342 auto ret1
= std::move(ret
);
344 assert(ret1(1, 2, 3));
346 auto ret2
= std::bind_front(std::move(value
), 1);
349 assert(ret2(1, 2, 3));
351 using RetT
= decltype(ret
);
352 static_assert( std::is_move_constructible
<RetT
>::value
);
353 static_assert( std::is_copy_constructible
<RetT
>::value
);
354 static_assert(!std::is_move_assignable
<RetT
>::value
);
355 static_assert(!std::is_copy_assignable
<RetT
>::value
);
358 CopyAssignableWrapper
value(true);
359 using RetT
= decltype(std::bind_front(value
, 1));
361 static_assert(std::is_move_constructible
<RetT
>::value
);
362 static_assert(std::is_copy_constructible
<RetT
>::value
);
363 static_assert(std::is_move_assignable
<RetT
>::value
);
364 static_assert(std::is_copy_assignable
<RetT
>::value
);
367 MoveAssignableWrapper
value(true);
368 using RetT
= decltype(std::bind_front(std::move(value
), 1));
370 static_assert( std::is_move_constructible
<RetT
>::value
);
371 static_assert(!std::is_copy_constructible
<RetT
>::value
);
372 static_assert( std::is_move_assignable
<RetT
>::value
);
373 static_assert(!std::is_copy_assignable
<RetT
>::value
);
377 // Make sure bind_front is SFINAE friendly
379 static_assert(!std::is_constructible_v
<NotCopyMove
, NotCopyMove
&>);
380 static_assert(!std::is_move_constructible_v
<NotCopyMove
>);
381 static_assert(!is_bind_frontable
<NotCopyMove
>::value
);
382 static_assert(!is_bind_frontable
<NotCopyMove
&>::value
);
384 auto takeAnything
= [](auto&& ...) { };
385 static_assert(!std::is_constructible_v
<MoveConstructible
, MoveConstructible
&>);
386 static_assert( std::is_move_constructible_v
<MoveConstructible
>);
387 static_assert( is_bind_frontable
<decltype(takeAnything
), MoveConstructible
>::value
);
388 static_assert(!is_bind_frontable
<decltype(takeAnything
), MoveConstructible
&>::value
);
390 static_assert( std::is_constructible_v
<NonConstCopyConstructible
, NonConstCopyConstructible
&>);
391 static_assert(!std::is_move_constructible_v
<NonConstCopyConstructible
>);
392 static_assert(!is_bind_frontable
<decltype(takeAnything
), NonConstCopyConstructible
&>::value
);
393 static_assert(!is_bind_frontable
<decltype(takeAnything
), NonConstCopyConstructible
>::value
);
396 // Make sure bind_front's unspecified type's operator() is SFINAE-friendly
398 using T
= decltype(std::bind_front(std::declval
<int(*)(int, int)>(), 1));
399 static_assert(!std::is_invocable
<T
>::value
);
400 static_assert( std::is_invocable
<T
, int>::value
);
401 static_assert(!std::is_invocable
<T
, void*>::value
);
402 static_assert(!std::is_invocable
<T
, int, int>::value
);
408 int main(int, char**) {
410 static_assert(test());