Skip to content

Commit c891704

Browse files
[libc++] Implement bind_back (#81055)
Implement `std::bind_back` function from P2387R3 "Pipe support for user-defined range adaptors".
1 parent 3bfd5c6 commit c891704

File tree

14 files changed

+582
-64
lines changed

14 files changed

+582
-64
lines changed

libcxx/docs/FeatureTestMacroTable.rst

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ Status
308308
---------------------------------------------------------- -----------------
309309
``__cpp_lib_associative_heterogeneous_erasure`` *unimplemented*
310310
---------------------------------------------------------- -----------------
311-
``__cpp_lib_bind_back`` *unimplemented*
311+
``__cpp_lib_bind_back`` ``202202L``
312312
---------------------------------------------------------- -----------------
313313
``__cpp_lib_byteswap`` ``202110L``
314314
---------------------------------------------------------- -----------------
@@ -398,8 +398,6 @@ Status
398398
---------------------------------------------------------- -----------------
399399
``__cpp_lib_atomic_min_max`` *unimplemented*
400400
---------------------------------------------------------- -----------------
401-
``__cpp_lib_bind_back`` *unimplemented*
402-
---------------------------------------------------------- -----------------
403401
``__cpp_lib_bind_front`` ``202306L``
404402
---------------------------------------------------------- -----------------
405403
``__cpp_lib_bitset`` ``202306L``

libcxx/docs/Status/Cxx23.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ Paper Status
4343
.. [#note-P0533R9] P0533R9: ``isfinite``, ``isinf``, ``isnan`` and ``isnormal`` are implemented.
4444
.. [#note-P1413R3] P1413R3: ``std::aligned_storage_t`` and ``std::aligned_union_t`` are marked deprecated, but
4545
clang doesn't issue a diagnostic for deprecated using template declarations.
46+
.. [#note-P2387R3] P2387R3: ``bind_back`` only
4647
.. [#note-P2520R0] P2520R0: Libc++ implemented this paper as a DR in C++20 as well.
4748
.. [#note-P2711R1] P2711R1: ``join_with_view`` hasn't been done yet since this type isn't implemented yet.
4849
.. [#note-P2770R0] P2770R0: ``join_with_view`` hasn't been done yet since this type isn't implemented yet.

libcxx/docs/Status/Cxx23Papers.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
"`P1413R3 <https://wg21.link/P1413R3>`__","LWG","Deprecate ``std::aligned_storage`` and ``std::aligned_union``","February 2022","|Complete| [#note-P1413R3]_",""
4646
"`P2255R2 <https://wg21.link/P2255R2>`__","LWG","A type trait to detect reference binding to temporary","February 2022","",""
4747
"`P2273R3 <https://wg21.link/P2273R3>`__","LWG","Making ``std::unique_ptr`` constexpr","February 2022","|Complete|","16.0"
48-
"`P2387R3 <https://wg21.link/P2387R3>`__","LWG","Pipe support for user-defined range adaptors","February 2022","","","|ranges|"
48+
"`P2387R3 <https://wg21.link/P2387R3>`__","LWG","Pipe support for user-defined range adaptors","February 2022","|Partial| [#note-P2387R3]_","","|ranges|"
4949
"`P2440R1 <https://wg21.link/P2440R1>`__","LWG","``ranges::iota``, ``ranges::shift_left`` and ``ranges::shift_right``","February 2022","","","|ranges|"
5050
"`P2441R2 <https://wg21.link/P2441R2>`__","LWG","``views::join_with``","February 2022","|In Progress|","","|ranges|"
5151
"`P2442R1 <https://wg21.link/P2442R1>`__","LWG","Windowing range adaptors: ``views::chunk`` and ``views::slide``","February 2022","","","|ranges|"

libcxx/include/__functional/bind_back.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,20 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __bind_back(_Fn&& __f, _Args&&... __args) n
6262
std::forward<_Fn>(__f), std::forward_as_tuple(std::forward<_Args>(__args)...));
6363
}
6464

65+
# if _LIBCPP_STD_VER >= 23
66+
template <class _Fn, class... _Args>
67+
_LIBCPP_HIDE_FROM_ABI constexpr auto bind_back(_Fn&& __f, _Args&&... __args) {
68+
static_assert(is_constructible_v<decay_t<_Fn>, _Fn>, "bind_back requires decay_t<F> to be constructible from F");
69+
static_assert(is_move_constructible_v<decay_t<_Fn>>, "bind_back requires decay_t<F> to be move constructible");
70+
static_assert((is_constructible_v<decay_t<_Args>, _Args> && ...),
71+
"bind_back requires all decay_t<Args> to be constructible from respective Args");
72+
static_assert((is_move_constructible_v<decay_t<_Args>> && ...),
73+
"bind_back requires all decay_t<Args> to be move constructible");
74+
return __bind_back_t<decay_t<_Fn>, tuple<decay_t<_Args>...>>(
75+
std::forward<_Fn>(__f), std::forward_as_tuple(std::forward<_Args>(__args)...));
76+
}
77+
# endif // _LIBCPP_STD_VER >= 23
78+
6579
#endif // _LIBCPP_STD_VER >= 20
6680

6781
_LIBCPP_END_NAMESPACE_STD

libcxx/include/functional

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,12 @@ binary_negate<Predicate> not2(const Predicate& pred);
207207
template <class F>
208208
constexpr unspecified not_fn(F&& f); // C++17, constexpr in C++20
209209
210+
// [func.bind.partial], function templates bind_front and bind_back
211+
template<class F, class... Args>
212+
constexpr unspecified bind_front(F&&, Args&&...); // C++20
213+
template<class F, class... Args>
214+
constexpr unspecified bind_back(F&&, Args&&...); // C++23
215+
210216
template<class T> struct is_bind_expression;
211217
template<class T> struct is_placeholder;
212218

libcxx/include/version

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ __cpp_lib_atomic_shared_ptr 201711L <atomic>
4141
__cpp_lib_atomic_value_initialization 201911L <atomic> <memory>
4242
__cpp_lib_atomic_wait 201907L <atomic>
4343
__cpp_lib_barrier 201907L <barrier>
44-
__cpp_lib_bind_back 202306L <functional>
45-
202202L // C++23
44+
__cpp_lib_bind_back 202202L <functional>
4645
__cpp_lib_bind_front 202306L <functional>
4746
201907L // C++20
4847
__cpp_lib_bit_cast 201806L <bit>
@@ -449,7 +448,7 @@ __cpp_lib_within_lifetime 202306L <type_traits>
449448
# define __cpp_lib_adaptor_iterator_pair_constructor 202106L
450449
# define __cpp_lib_allocate_at_least 202302L
451450
// # define __cpp_lib_associative_heterogeneous_erasure 202110L
452-
// # define __cpp_lib_bind_back 202202L
451+
# define __cpp_lib_bind_back 202202L
453452
# define __cpp_lib_byteswap 202110L
454453
# define __cpp_lib_constexpr_bitset 202207L
455454
# define __cpp_lib_constexpr_charconv 202207L
@@ -498,8 +497,6 @@ __cpp_lib_within_lifetime 202306L <type_traits>
498497
#if _LIBCPP_STD_VER >= 26
499498
// # define __cpp_lib_associative_heterogeneous_insertion 202306L
500499
// # define __cpp_lib_atomic_min_max 202403L
501-
# undef __cpp_lib_bind_back
502-
// # define __cpp_lib_bind_back 202306L
503500
# undef __cpp_lib_bind_front
504501
# define __cpp_lib_bind_front 202306L
505502
# define __cpp_lib_bitset 202306L

libcxx/modules/std/functional.inc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,10 @@ export namespace std {
5656
using std::not_fn;
5757

5858
// [func.bind.partial], function templates bind_front and bind_back
59-
// using std::bind_back;
6059
using std::bind_front;
60+
#if _LIBCPP_STD_VER >= 23
61+
using std::bind_back;
62+
#endif
6163

6264
// [func.bind], bind
6365
using std::is_bind_expression;

libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
/* Constant Value
1919
__cpp_lib_bind_back 202202L [C++23]
20-
202306L [C++26]
2120
__cpp_lib_bind_front 201907L [C++20]
2221
202306L [C++26]
2322
__cpp_lib_boyer_moore_searcher 201603L [C++17]
@@ -337,17 +336,11 @@
337336

338337
#elif TEST_STD_VER == 23
339338

340-
# if !defined(_LIBCPP_VERSION)
341-
# ifndef __cpp_lib_bind_back
342-
# error "__cpp_lib_bind_back should be defined in c++23"
343-
# endif
344-
# if __cpp_lib_bind_back != 202202L
345-
# error "__cpp_lib_bind_back should have the value 202202L in c++23"
346-
# endif
347-
# else // _LIBCPP_VERSION
348-
# ifdef __cpp_lib_bind_back
349-
# error "__cpp_lib_bind_back should not be defined because it is unimplemented in libc++!"
350-
# endif
339+
# ifndef __cpp_lib_bind_back
340+
# error "__cpp_lib_bind_back should be defined in c++23"
341+
# endif
342+
# if __cpp_lib_bind_back != 202202L
343+
# error "__cpp_lib_bind_back should have the value 202202L in c++23"
351344
# endif
352345

353346
# ifndef __cpp_lib_bind_front
@@ -447,17 +440,11 @@
447440

448441
#elif TEST_STD_VER > 23
449442

450-
# if !defined(_LIBCPP_VERSION)
451-
# ifndef __cpp_lib_bind_back
452-
# error "__cpp_lib_bind_back should be defined in c++26"
453-
# endif
454-
# if __cpp_lib_bind_back != 202306L
455-
# error "__cpp_lib_bind_back should have the value 202306L in c++26"
456-
# endif
457-
# else // _LIBCPP_VERSION
458-
# ifdef __cpp_lib_bind_back
459-
# error "__cpp_lib_bind_back should not be defined because it is unimplemented in libc++!"
460-
# endif
443+
# ifndef __cpp_lib_bind_back
444+
# error "__cpp_lib_bind_back should be defined in c++26"
445+
# endif
446+
# if __cpp_lib_bind_back != 202202L
447+
# error "__cpp_lib_bind_back should have the value 202202L in c++26"
461448
# endif
462449

463450
# ifndef __cpp_lib_bind_front

libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
__cpp_lib_atomic_wait 201907L [C++20]
4040
__cpp_lib_barrier 201907L [C++20]
4141
__cpp_lib_bind_back 202202L [C++23]
42-
202306L [C++26]
4342
__cpp_lib_bind_front 201907L [C++20]
4443
202306L [C++26]
4544
__cpp_lib_bit_cast 201806L [C++20]
@@ -4605,17 +4604,11 @@
46054604
# endif
46064605
# endif
46074606

4608-
# if !defined(_LIBCPP_VERSION)
4609-
# ifndef __cpp_lib_bind_back
4610-
# error "__cpp_lib_bind_back should be defined in c++23"
4611-
# endif
4612-
# if __cpp_lib_bind_back != 202202L
4613-
# error "__cpp_lib_bind_back should have the value 202202L in c++23"
4614-
# endif
4615-
# else // _LIBCPP_VERSION
4616-
# ifdef __cpp_lib_bind_back
4617-
# error "__cpp_lib_bind_back should not be defined because it is unimplemented in libc++!"
4618-
# endif
4607+
# ifndef __cpp_lib_bind_back
4608+
# error "__cpp_lib_bind_back should be defined in c++23"
4609+
# endif
4610+
# if __cpp_lib_bind_back != 202202L
4611+
# error "__cpp_lib_bind_back should have the value 202202L in c++23"
46194612
# endif
46204613

46214614
# ifndef __cpp_lib_bind_front
@@ -6240,17 +6233,11 @@
62406233
# endif
62416234
# endif
62426235

6243-
# if !defined(_LIBCPP_VERSION)
6244-
# ifndef __cpp_lib_bind_back
6245-
# error "__cpp_lib_bind_back should be defined in c++26"
6246-
# endif
6247-
# if __cpp_lib_bind_back != 202306L
6248-
# error "__cpp_lib_bind_back should have the value 202306L in c++26"
6249-
# endif
6250-
# else // _LIBCPP_VERSION
6251-
# ifdef __cpp_lib_bind_back
6252-
# error "__cpp_lib_bind_back should not be defined because it is unimplemented in libc++!"
6253-
# endif
6236+
# ifndef __cpp_lib_bind_back
6237+
# error "__cpp_lib_bind_back should be defined in c++26"
6238+
# endif
6239+
# if __cpp_lib_bind_back != 202202L
6240+
# error "__cpp_lib_bind_back should have the value 202202L in c++26"
62546241
# endif
62556242

62566243
# ifndef __cpp_lib_bind_front

0 commit comments

Comments
 (0)