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&&...);
20 #include <type_traits>
23 #include "callable_types.h"
24 #include "test_macros.h"
27 enum { none
, copy
, move
} copy_kind
;
29 constexpr CopyMoveInfo() : copy_kind(none
) {}
30 constexpr CopyMoveInfo(CopyMoveInfo
const&) : copy_kind(copy
) {}
31 constexpr CopyMoveInfo(CopyMoveInfo
&&) : copy_kind(move
) {}
34 template <class ...Args
>
35 struct is_bind_frontable
{
36 template <class ...LocalArgs
>
38 -> decltype((void)std::bind_front(std::declval
<LocalArgs
>()...), std::true_type());
41 static std::false_type
test(...);
43 static constexpr bool value
= decltype(test
<Args
...>(0))::value
;
47 NotCopyMove() = delete;
48 NotCopyMove(const NotCopyMove
&) = delete;
49 NotCopyMove(NotCopyMove
&&) = delete;
50 template <class ...Args
>
51 void operator()(Args
&& ...) const { }
54 struct NonConstCopyConstructible
{
55 explicit NonConstCopyConstructible() {}
56 NonConstCopyConstructible(NonConstCopyConstructible
&) {}
59 struct MoveConstructible
{
60 explicit MoveConstructible() {}
61 MoveConstructible(MoveConstructible
&&) {}
65 template <class ...Args
>
66 constexpr auto operator()(Args
&& ...args
) const {
67 return std::make_tuple(std::forward
<Args
>(args
)...);
74 constexpr bool operator==(Elem
<Y
> const&) const
78 constexpr bool test() {
79 // Bind arguments, call without arguments
82 auto f
= std::bind_front(MakeTuple
{});
83 assert(f() == std::make_tuple());
86 auto f
= std::bind_front(MakeTuple
{}, Elem
<1>{});
87 assert(f() == std::make_tuple(Elem
<1>{}));
90 auto f
= std::bind_front(MakeTuple
{}, Elem
<1>{}, Elem
<2>{});
91 assert(f() == std::make_tuple(Elem
<1>{}, Elem
<2>{}));
94 auto f
= std::bind_front(MakeTuple
{}, Elem
<1>{}, Elem
<2>{}, Elem
<3>{});
95 assert(f() == std::make_tuple(Elem
<1>{}, Elem
<2>{}, Elem
<3>{}));
99 // Bind no arguments, call with arguments
102 auto f
= std::bind_front(MakeTuple
{});
103 assert(f(Elem
<1>{}) == std::make_tuple(Elem
<1>{}));
106 auto f
= std::bind_front(MakeTuple
{});
107 assert(f(Elem
<1>{}, Elem
<2>{}) == std::make_tuple(Elem
<1>{}, Elem
<2>{}));
110 auto f
= std::bind_front(MakeTuple
{});
111 assert(f(Elem
<1>{}, Elem
<2>{}, Elem
<3>{}) == std::make_tuple(Elem
<1>{}, Elem
<2>{}, Elem
<3>{}));
115 // Bind arguments, call with arguments
118 auto f
= std::bind_front(MakeTuple
{}, Elem
<1>{});
119 assert(f(Elem
<10>{}) == std::make_tuple(Elem
<1>{}, Elem
<10>{}));
122 auto f
= std::bind_front(MakeTuple
{}, Elem
<1>{}, Elem
<2>{});
123 assert(f(Elem
<10>{}) == std::make_tuple(Elem
<1>{}, Elem
<2>{}, Elem
<10>{}));
126 auto f
= std::bind_front(MakeTuple
{}, Elem
<1>{}, Elem
<2>{}, Elem
<3>{});
127 assert(f(Elem
<10>{}) == std::make_tuple(Elem
<1>{}, Elem
<2>{}, Elem
<3>{}, Elem
<10>{}));
131 auto f
= std::bind_front(MakeTuple
{}, Elem
<1>{});
132 assert(f(Elem
<10>{}, Elem
<11>{}) == std::make_tuple(Elem
<1>{}, Elem
<10>{}, Elem
<11>{}));
135 auto f
= std::bind_front(MakeTuple
{}, Elem
<1>{}, Elem
<2>{});
136 assert(f(Elem
<10>{}, Elem
<11>{}) == std::make_tuple(Elem
<1>{}, Elem
<2>{}, Elem
<10>{}, Elem
<11>{}));
139 auto f
= std::bind_front(MakeTuple
{}, Elem
<1>{}, Elem
<2>{}, Elem
<3>{});
140 assert(f(Elem
<10>{}, Elem
<11>{}) == std::make_tuple(Elem
<1>{}, Elem
<2>{}, Elem
<3>{}, Elem
<10>{}, Elem
<11>{}));
144 // Basic tests with fundamental types
149 auto add
= [](int x
, int y
) { return x
+ y
; };
150 auto addN
= [](int a
, int b
, int c
, int d
, int e
, int f
) { return a
+ b
+ c
+ d
+ e
+ f
; };
151 auto add_ref
= [&](int x
, int y
) -> int& { return sum
= x
+ y
; };
152 auto add_rref
= [&](int x
, int y
) -> int&& { return std::move(sum
= x
+ y
); };
154 auto a
= std::bind_front(add
, m
, n
);
157 auto b
= std::bind_front(addN
, m
, n
, m
, m
, m
, m
);
160 auto c
= std::bind_front(addN
, n
, m
);
161 assert(c(1, 1, 1, 1) == 7);
163 auto d
= std::bind_front(add_ref
, n
, m
);
164 std::same_as
<int&> decltype(auto) dresult(d());
165 assert(dresult
== 3);
167 auto e
= std::bind_front(add_rref
, n
, m
);
168 std::same_as
<int&&> decltype(auto) eresult(e());
169 assert(eresult
== 3);
171 auto f
= std::bind_front(add
, n
);
174 auto g
= std::bind_front(add
, n
, 1);
177 auto h
= std::bind_front(addN
, 1, 1, 1);
178 assert(h(2, 2, 2) == 9);
180 auto i
= std::bind_front(add_ref
, n
);
181 std::same_as
<int&> decltype(auto) iresult(i(5));
182 assert(iresult
== 7);
184 auto j
= std::bind_front(add_rref
, m
);
185 std::same_as
<int&&> decltype(auto) jresult(j(4));
186 assert(jresult
== 5);
189 // Make sure we don't treat std::reference_wrapper specially.
191 auto add
= [](std::reference_wrapper
<int> a
, std::reference_wrapper
<int> b
) {
192 return a
.get() + b
.get();
195 auto f
= std::bind_front(add
, std::ref(i
));
196 assert(f(std::ref(j
)) == 3);
199 // Make sure we can call a function that's a pointer to a member function.
201 struct MemberFunction
{
202 constexpr bool foo(int, int) { return true; }
204 MemberFunction value
;
205 auto fn
= std::bind_front(&MemberFunction::foo
, value
, 0);
209 // Make sure that we copy the bound arguments into the unspecified-type.
211 auto add
= [](int x
, int y
) { return x
+ y
; };
213 auto i
= std::bind_front(add
, n
, 1);
218 // Make sure we pass the bound arguments to the function object
219 // with the right value category.
222 auto wasCopied
= [](CopyMoveInfo info
) {
223 return info
.copy_kind
== CopyMoveInfo::copy
;
226 auto copied
= std::bind_front(wasCopied
, info
);
231 auto wasMoved
= [](CopyMoveInfo info
) {
232 return info
.copy_kind
== CopyMoveInfo::move
;
235 auto moved
= std::bind_front(wasMoved
, info
);
236 assert(std::move(moved
)());
240 // Make sure we call the correctly cv-ref qualified operator() based on the
241 // value category of the bind_front unspecified-type.
244 constexpr int operator()() & { return 1; }
245 constexpr int operator()() const& { return 2; }
246 constexpr int operator()() && { return 3; }
247 constexpr int operator()() const&& { return 4; }
249 auto x
= std::bind_front(F
{});
250 using X
= decltype(x
);
251 assert(static_cast<X
&>(x
)() == 1);
252 assert(static_cast<X
const&>(x
)() == 2);
253 assert(static_cast<X
&&>(x
)() == 3);
254 assert(static_cast<X
const&&>(x
)() == 4);
257 // Make sure the bind_front unspecified-type is NOT invocable when the call would select a
258 // differently-qualified operator().
260 // For example, if the call to `operator()() &` is ill-formed, the call to the unspecified-type
261 // should be ill-formed and not fall back to the `operator()() const&` overload.
263 // Make sure we delete the & overload when the underlying call isn't valid
266 void operator()() & = delete;
267 void operator()() const&;
268 void operator()() &&;
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 // There's no way to make sure we delete the const& overload when the underlying call isn't valid,
279 // so we can't check this one.
281 // Make sure we delete the && overload when the underlying call isn't valid
285 void operator()() const&;
286 void operator()() && = delete;
287 void operator()() const&&;
289 using X
= decltype(std::bind_front(F
{}));
290 static_assert( std::is_invocable_v
<X
&>);
291 static_assert( std::is_invocable_v
<X
const&>);
292 static_assert(!std::is_invocable_v
<X
>);
293 static_assert( std::is_invocable_v
<X
const>);
296 // Make sure we delete the const&& overload when the underlying call isn't valid
300 void operator()() const&;
301 void operator()() &&;
302 void operator()() const&& = delete;
304 using X
= decltype(std::bind_front(F
{}));
305 static_assert( std::is_invocable_v
<X
&>);
306 static_assert( std::is_invocable_v
<X
const&>);
307 static_assert( std::is_invocable_v
<X
>);
308 static_assert(!std::is_invocable_v
<X
const>);
312 // Some examples by Tim Song
317 void operator()(T
&&) const &;
318 void operator()(T
&&) && = delete;
320 using X
= decltype(std::bind_front(F
{}));
321 static_assert(!std::is_invocable_v
<X
, T
>);
327 void operator()(T
const&) const;
328 void operator()(T
&&) const = delete;
330 using X
= decltype(std::bind_front(F
{}, T
{}));
331 static_assert(!std::is_invocable_v
<X
>);
335 // Test properties of the constructor of the unspecified-type returned by bind_front.
338 MoveOnlyCallable
<bool> value(true);
339 auto ret
= std::bind_front(std::move(value
), 1);
341 assert(ret(1, 2, 3));
343 auto ret1
= std::move(ret
);
346 assert(ret1(1, 2, 3));
348 using RetT
= decltype(ret
);
349 static_assert( std::is_move_constructible
<RetT
>::value
);
350 static_assert(!std::is_copy_constructible
<RetT
>::value
);
351 static_assert(!std::is_move_assignable
<RetT
>::value
);
352 static_assert(!std::is_copy_assignable
<RetT
>::value
);
355 CopyCallable
<bool> value(true);
356 auto ret
= std::bind_front(value
, 1);
358 assert(ret(1, 2, 3));
360 auto ret1
= std::move(ret
);
362 assert(ret1(1, 2, 3));
364 auto ret2
= std::bind_front(std::move(value
), 1);
367 assert(ret2(1, 2, 3));
369 using RetT
= decltype(ret
);
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
);
376 CopyAssignableWrapper
value(true);
377 using RetT
= decltype(std::bind_front(value
, 1));
379 static_assert(std::is_move_constructible
<RetT
>::value
);
380 static_assert(std::is_copy_constructible
<RetT
>::value
);
381 static_assert(std::is_move_assignable
<RetT
>::value
);
382 static_assert(std::is_copy_assignable
<RetT
>::value
);
385 MoveAssignableWrapper
value(true);
386 using RetT
= decltype(std::bind_front(std::move(value
), 1));
388 static_assert( std::is_move_constructible
<RetT
>::value
);
389 static_assert(!std::is_copy_constructible
<RetT
>::value
);
390 static_assert( std::is_move_assignable
<RetT
>::value
);
391 static_assert(!std::is_copy_assignable
<RetT
>::value
);
395 // Make sure bind_front is SFINAE friendly
397 static_assert(!std::is_constructible_v
<NotCopyMove
, NotCopyMove
&>);
398 static_assert(!std::is_move_constructible_v
<NotCopyMove
>);
399 static_assert(!is_bind_frontable
<NotCopyMove
>::value
);
400 static_assert(!is_bind_frontable
<NotCopyMove
&>::value
);
402 auto takeAnything
= [](auto&& ...) { };
403 static_assert(!std::is_constructible_v
<MoveConstructible
, MoveConstructible
&>);
404 static_assert( std::is_move_constructible_v
<MoveConstructible
>);
405 static_assert( is_bind_frontable
<decltype(takeAnything
), MoveConstructible
>::value
);
406 static_assert(!is_bind_frontable
<decltype(takeAnything
), MoveConstructible
&>::value
);
408 static_assert( std::is_constructible_v
<NonConstCopyConstructible
, NonConstCopyConstructible
&>);
409 static_assert(!std::is_move_constructible_v
<NonConstCopyConstructible
>);
410 static_assert(!is_bind_frontable
<decltype(takeAnything
), NonConstCopyConstructible
&>::value
);
411 static_assert(!is_bind_frontable
<decltype(takeAnything
), NonConstCopyConstructible
>::value
);
414 // Make sure bind_front's unspecified type's operator() is SFINAE-friendly
416 using T
= decltype(std::bind_front(std::declval
<int(*)(int, int)>(), 1));
417 static_assert(!std::is_invocable
<T
>::value
);
418 static_assert( std::is_invocable
<T
, int>::value
);
419 static_assert(!std::is_invocable
<T
, void*>::value
);
420 static_assert(!std::is_invocable
<T
, int, int>::value
);
426 int main(int, char**) {
428 static_assert(test());