Skip to content

Commit dcda573

Browse files
committed
[libc++] Implement bind_back
Implement `std::bind_back` function from P2387R3 "Pipe support for user-defined range adaptors".
1 parent d273a19 commit dcda573

File tree

13 files changed

+539
-58
lines changed

13 files changed

+539
-58
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
--------------------------------------------------- -----------------
@@ -392,8 +392,6 @@ Status
392392
---------------------------------------------------------------------
393393
``__cpp_lib_associative_heterogeneous_insertion`` *unimplemented*
394394
--------------------------------------------------- -----------------
395-
``__cpp_lib_bind_back`` *unimplemented*
396-
--------------------------------------------------- -----------------
397395
``__cpp_lib_bind_front`` ``202306L``
398396
--------------------------------------------------- -----------------
399397
``__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
@@ -40,8 +40,7 @@ __cpp_lib_atomic_shared_ptr 201711L <atomic>
4040
__cpp_lib_atomic_value_initialization 201911L <atomic> <memory>
4141
__cpp_lib_atomic_wait 201907L <atomic>
4242
__cpp_lib_barrier 201907L <barrier>
43-
__cpp_lib_bind_back 202306L <functional>
44-
202202L // C++23
43+
__cpp_lib_bind_back 202202L <functional>
4544
__cpp_lib_bind_front 202306L <functional>
4645
201907L // C++20
4746
__cpp_lib_bit_cast 201806L <bit>
@@ -439,7 +438,7 @@ __cpp_lib_within_lifetime 202306L <type_traits>
439438
# define __cpp_lib_adaptor_iterator_pair_constructor 202106L
440439
# define __cpp_lib_allocate_at_least 202302L
441440
// # define __cpp_lib_associative_heterogeneous_erasure 202110L
442-
// # define __cpp_lib_bind_back 202202L
441+
# define __cpp_lib_bind_back 202202L
443442
# define __cpp_lib_byteswap 202110L
444443
# define __cpp_lib_constexpr_bitset 202207L
445444
# define __cpp_lib_constexpr_charconv 202207L
@@ -485,8 +484,6 @@ __cpp_lib_within_lifetime 202306L <type_traits>
485484

486485
#if _LIBCPP_STD_VER >= 26
487486
// # define __cpp_lib_associative_heterogeneous_insertion 202306L
488-
# undef __cpp_lib_bind_back
489-
// # define __cpp_lib_bind_back 202306L
490487
# undef __cpp_lib_bind_front
491488
# define __cpp_lib_bind_front 202306L
492489
# 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]
@@ -320,17 +319,11 @@
320319

321320
#elif TEST_STD_VER == 23
322321

323-
# if !defined(_LIBCPP_VERSION)
324-
# ifndef __cpp_lib_bind_back
325-
# error "__cpp_lib_bind_back should be defined in c++23"
326-
# endif
327-
# if __cpp_lib_bind_back != 202202L
328-
# error "__cpp_lib_bind_back should have the value 202202L in c++23"
329-
# endif
330-
# else // _LIBCPP_VERSION
331-
# ifdef __cpp_lib_bind_back
332-
# error "__cpp_lib_bind_back should not be defined because it is unimplemented in libc++!"
333-
# endif
322+
# ifndef __cpp_lib_bind_back
323+
# error "__cpp_lib_bind_back should be defined in c++23"
324+
# endif
325+
# if __cpp_lib_bind_back != 202202L
326+
# error "__cpp_lib_bind_back should have the value 202202L in c++23"
334327
# endif
335328

336329
# ifndef __cpp_lib_bind_front
@@ -426,17 +419,11 @@
426419

427420
#elif TEST_STD_VER > 23
428421

429-
# if !defined(_LIBCPP_VERSION)
430-
# ifndef __cpp_lib_bind_back
431-
# error "__cpp_lib_bind_back should be defined in c++26"
432-
# endif
433-
# if __cpp_lib_bind_back != 202306L
434-
# error "__cpp_lib_bind_back should have the value 202306L in c++26"
435-
# endif
436-
# else // _LIBCPP_VERSION
437-
# ifdef __cpp_lib_bind_back
438-
# error "__cpp_lib_bind_back should not be defined because it is unimplemented in libc++!"
439-
# endif
422+
# ifndef __cpp_lib_bind_back
423+
# error "__cpp_lib_bind_back should be defined in c++26"
424+
# endif
425+
# if __cpp_lib_bind_back != 202202L
426+
# error "__cpp_lib_bind_back should have the value 202202L in c++26"
440427
# endif
441428

442429
# 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
@@ -38,7 +38,6 @@
3838
__cpp_lib_atomic_wait 201907L [C++20]
3939
__cpp_lib_barrier 201907L [C++20]
4040
__cpp_lib_bind_back 202202L [C++23]
41-
202306L [C++26]
4241
__cpp_lib_bind_front 201907L [C++20]
4342
202306L [C++26]
4443
__cpp_lib_bit_cast 201806L [C++20]
@@ -4465,17 +4464,11 @@
44654464
# endif
44664465
# endif
44674466

4468-
# if !defined(_LIBCPP_VERSION)
4469-
# ifndef __cpp_lib_bind_back
4470-
# error "__cpp_lib_bind_back should be defined in c++23"
4471-
# endif
4472-
# if __cpp_lib_bind_back != 202202L
4473-
# error "__cpp_lib_bind_back should have the value 202202L in c++23"
4474-
# endif
4475-
# else // _LIBCPP_VERSION
4476-
# ifdef __cpp_lib_bind_back
4477-
# error "__cpp_lib_bind_back should not be defined because it is unimplemented in libc++!"
4478-
# endif
4467+
# ifndef __cpp_lib_bind_back
4468+
# error "__cpp_lib_bind_back should be defined in c++23"
4469+
# endif
4470+
# if __cpp_lib_bind_back != 202202L
4471+
# error "__cpp_lib_bind_back should have the value 202202L in c++23"
44794472
# endif
44804473

44814474
# ifndef __cpp_lib_bind_front
@@ -6053,17 +6046,11 @@
60536046
# endif
60546047
# endif
60556048

6056-
# if !defined(_LIBCPP_VERSION)
6057-
# ifndef __cpp_lib_bind_back
6058-
# error "__cpp_lib_bind_back should be defined in c++26"
6059-
# endif
6060-
# if __cpp_lib_bind_back != 202306L
6061-
# error "__cpp_lib_bind_back should have the value 202306L in c++26"
6062-
# endif
6063-
# else // _LIBCPP_VERSION
6064-
# ifdef __cpp_lib_bind_back
6065-
# error "__cpp_lib_bind_back should not be defined because it is unimplemented in libc++!"
6066-
# endif
6049+
# ifndef __cpp_lib_bind_back
6050+
# error "__cpp_lib_bind_back should be defined in c++26"
6051+
# endif
6052+
# if __cpp_lib_bind_back != 202202L
6053+
# error "__cpp_lib_bind_back should have the value 202202L in c++26"
60676054
# endif
60686055

60696056
# ifndef __cpp_lib_bind_front

0 commit comments

Comments
 (0)