-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[libc++] Implement bind_back
#81055
[libc++] Implement bind_back
#81055
Conversation
@llvm/pr-subscribers-libcxx Author: Jakub Mazurkiewicz (JMazurkiewicz) Changes
Patch is 43.54 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/81055.diff 15 Files Affected:
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index a5c6fa22cec06c..a3be1b9e71fc3f 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -308,7 +308,7 @@ Status
--------------------------------------------------- -----------------
``__cpp_lib_associative_heterogeneous_erasure`` *unimplemented*
--------------------------------------------------- -----------------
- ``__cpp_lib_bind_back`` *unimplemented*
+ ``__cpp_lib_bind_back`` ``202202L``
--------------------------------------------------- -----------------
``__cpp_lib_byteswap`` ``202110L``
--------------------------------------------------- -----------------
@@ -392,10 +392,6 @@ Status
---------------------------------------------------------------------
``__cpp_lib_associative_heterogeneous_insertion`` *unimplemented*
--------------------------------------------------- -----------------
- ``__cpp_lib_bind_back`` *unimplemented*
- --------------------------------------------------- -----------------
- ``__cpp_lib_bind_front`` ``202306L``
- --------------------------------------------------- -----------------
``__cpp_lib_bitset`` ``202306L``
--------------------------------------------------- -----------------
``__cpp_lib_copyable_function`` *unimplemented*
diff --git a/libcxx/docs/Status/Cxx23.rst b/libcxx/docs/Status/Cxx23.rst
index 3e6e33f08c7ccf..a3a0d8b81e88f9 100644
--- a/libcxx/docs/Status/Cxx23.rst
+++ b/libcxx/docs/Status/Cxx23.rst
@@ -43,6 +43,7 @@ Paper Status
.. [#note-P0533R9] P0533R9: ``isfinite``, ``isinf``, ``isnan`` and ``isnormal`` are implemented.
.. [#note-P1413R3] P1413R3: ``std::aligned_storage_t`` and ``std::aligned_union_t`` are marked deprecated, but
clang doesn't issue a diagnostic for deprecated using template declarations.
+ .. [#note-P2387R3] P2387R3: ``bind_back`` only
.. [#note-P2520R0] P2520R0: Libc++ implemented this paper as a DR in C++20 as well.
.. [#note-P2711R1] P2711R1: ``join_with_view`` hasn't been done yet since this type isn't implemented yet.
.. [#note-P2770R0] P2770R0: ``join_with_view`` hasn't been done yet since this type isn't implemented yet.
diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv
index eb415ed8c031fa..aebc2ffe5b067a 100644
--- a/libcxx/docs/Status/Cxx23Papers.csv
+++ b/libcxx/docs/Status/Cxx23Papers.csv
@@ -45,7 +45,7 @@
"`P1413R3 <https://wg21.link/P1413R3>`__","LWG","Deprecate ``std::aligned_storage`` and ``std::aligned_union``","February 2022","|Complete| [#note-P1413R3]_",""
"`P2255R2 <https://wg21.link/P2255R2>`__","LWG","A type trait to detect reference binding to temporary","February 2022","",""
"`P2273R3 <https://wg21.link/P2273R3>`__","LWG","Making ``std::unique_ptr`` constexpr","February 2022","|Complete|","16.0"
-"`P2387R3 <https://wg21.link/P2387R3>`__","LWG","Pipe support for user-defined range adaptors","February 2022","","","|ranges|"
+"`P2387R3 <https://wg21.link/P2387R3>`__","LWG","Pipe support for user-defined range adaptors","February 2022","|Partial| [#note-P2387R3]_","","|ranges|"
"`P2440R1 <https://wg21.link/P2440R1>`__","LWG","``ranges::iota``, ``ranges::shift_left`` and ``ranges::shift_right``","February 2022","","","|ranges|"
"`P2441R2 <https://wg21.link/P2441R2>`__","LWG","``views::join_with``","February 2022","|In Progress|","","|ranges|"
"`P2442R1 <https://wg21.link/P2442R1>`__","LWG","Windowing range adaptors: ``views::chunk`` and ``views::slide``","February 2022","","","|ranges|"
diff --git a/libcxx/include/__functional/bind_back.h b/libcxx/include/__functional/bind_back.h
index ce26d3b70630f3..2baab3e252d3d1 100644
--- a/libcxx/include/__functional/bind_back.h
+++ b/libcxx/include/__functional/bind_back.h
@@ -62,6 +62,20 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __bind_back(_Fn&& __f, _Args&&... __args) n
std::forward<_Fn>(__f), std::forward_as_tuple(std::forward<_Args>(__args)...));
}
+# if _LIBCPP_STD_VER >= 23
+template <class _Fn, class... _Args>
+ requires is_constructible_v<decay_t<_Fn>, _Fn> && is_move_constructible_v<decay_t<_Fn>> &&
+ (is_constructible_v<decay_t<_Args>, _Args> && ...) && (is_move_constructible_v<decay_t<_Args>> && ...)
+_LIBCPP_HIDE_FROM_ABI constexpr auto bind_back(_Fn&& __f, _Args&&... __args) noexcept(
+ noexcept(__bind_back_t<decay_t<_Fn>, tuple<decay_t<_Args>...>>(
+ std::forward<_Fn>(__f), std::forward_as_tuple(std::forward<_Args>(__args)...))))
+ -> decltype(__bind_back_t<decay_t<_Fn>, tuple<decay_t<_Args>...>>(
+ std::forward<_Fn>(__f), std::forward_as_tuple(std::forward<_Args>(__args)...))) {
+ return __bind_back_t<decay_t<_Fn>, tuple<decay_t<_Args>...>>(
+ std::forward<_Fn>(__f), std::forward_as_tuple(std::forward<_Args>(__args)...));
+}
+# endif // _LIBCPP_STD_VER >= 20
+
#endif // _LIBCPP_STD_VER >= 20
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/functional b/libcxx/include/functional
index fd99e11fb18180..d72ebb2310c5ae 100644
--- a/libcxx/include/functional
+++ b/libcxx/include/functional
@@ -207,6 +207,12 @@ binary_negate<Predicate> not2(const Predicate& pred);
template <class F>
constexpr unspecified not_fn(F&& f); // C++17, constexpr in C++20
+// [func.bind.partial], function templates bind_front and bind_back
+template<class F, class... Args>
+ constexpr unspecified bind_front(F&&, Args&&...); // C++20
+template<class F, class... Args>
+ constexpr unspecified bind_back(F&&, Args&&...); // C++23
+
template<class T> struct is_bind_expression;
template<class T> struct is_placeholder;
diff --git a/libcxx/include/version b/libcxx/include/version
index b18927a2bc38c2..5dc73becc943c6 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -40,10 +40,8 @@ __cpp_lib_atomic_shared_ptr 201711L <atomic>
__cpp_lib_atomic_value_initialization 201911L <atomic> <memory>
__cpp_lib_atomic_wait 201907L <atomic>
__cpp_lib_barrier 201907L <barrier>
-__cpp_lib_bind_back 202306L <functional>
- 202202L // C++23
-__cpp_lib_bind_front 202306L <functional>
- 201907L // C++20
+__cpp_lib_bind_back 202202L <functional>
+__cpp_lib_bind_front 201907L <functional>
__cpp_lib_bit_cast 201806L <bit>
__cpp_lib_bitops 201907L <bit>
__cpp_lib_bitset 202306L <bitset>
@@ -439,7 +437,7 @@ __cpp_lib_within_lifetime 202306L <type_traits>
# define __cpp_lib_adaptor_iterator_pair_constructor 202106L
# define __cpp_lib_allocate_at_least 202302L
// # define __cpp_lib_associative_heterogeneous_erasure 202110L
-// # define __cpp_lib_bind_back 202202L
+# define __cpp_lib_bind_back 202202L
# define __cpp_lib_byteswap 202110L
# define __cpp_lib_constexpr_bitset 202207L
# define __cpp_lib_constexpr_charconv 202207L
@@ -485,10 +483,6 @@ __cpp_lib_within_lifetime 202306L <type_traits>
#if _LIBCPP_STD_VER >= 26
// # define __cpp_lib_associative_heterogeneous_insertion 202306L
-# undef __cpp_lib_bind_back
-// # define __cpp_lib_bind_back 202306L
-# undef __cpp_lib_bind_front
-# define __cpp_lib_bind_front 202306L
# define __cpp_lib_bitset 202306L
// # define __cpp_lib_copyable_function 202306L
// # define __cpp_lib_debugging 202311L
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp
index 72c96c62b64c45..db4c183544caa2 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp
@@ -17,9 +17,7 @@
/* Constant Value
__cpp_lib_bind_back 202202L [C++23]
- 202306L [C++26]
__cpp_lib_bind_front 201907L [C++20]
- 202306L [C++26]
__cpp_lib_boyer_moore_searcher 201603L [C++17]
__cpp_lib_constexpr_functional 201907L [C++20]
__cpp_lib_copyable_function 202306L [C++26]
@@ -320,17 +318,11 @@
#elif TEST_STD_VER == 23
-# if !defined(_LIBCPP_VERSION)
-# ifndef __cpp_lib_bind_back
-# error "__cpp_lib_bind_back should be defined in c++23"
-# endif
-# if __cpp_lib_bind_back != 202202L
-# error "__cpp_lib_bind_back should have the value 202202L in c++23"
-# endif
-# else // _LIBCPP_VERSION
-# ifdef __cpp_lib_bind_back
-# error "__cpp_lib_bind_back should not be defined because it is unimplemented in libc++!"
-# endif
+# ifndef __cpp_lib_bind_back
+# error "__cpp_lib_bind_back should be defined in c++23"
+# endif
+# if __cpp_lib_bind_back != 202202L
+# error "__cpp_lib_bind_back should have the value 202202L in c++23"
# endif
# ifndef __cpp_lib_bind_front
@@ -426,24 +418,18 @@
#elif TEST_STD_VER > 23
-# if !defined(_LIBCPP_VERSION)
-# ifndef __cpp_lib_bind_back
-# error "__cpp_lib_bind_back should be defined in c++26"
-# endif
-# if __cpp_lib_bind_back != 202306L
-# error "__cpp_lib_bind_back should have the value 202306L in c++26"
-# endif
-# else // _LIBCPP_VERSION
-# ifdef __cpp_lib_bind_back
-# error "__cpp_lib_bind_back should not be defined because it is unimplemented in libc++!"
-# endif
+# ifndef __cpp_lib_bind_back
+# error "__cpp_lib_bind_back should be defined in c++26"
+# endif
+# if __cpp_lib_bind_back != 202202L
+# error "__cpp_lib_bind_back should have the value 202202L in c++26"
# endif
# ifndef __cpp_lib_bind_front
# error "__cpp_lib_bind_front should be defined in c++26"
# endif
-# if __cpp_lib_bind_front != 202306L
-# error "__cpp_lib_bind_front should have the value 202306L in c++26"
+# if __cpp_lib_bind_front != 201907L
+# error "__cpp_lib_bind_front should have the value 201907L in c++26"
# endif
# ifndef __cpp_lib_boyer_moore_searcher
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index 14271308624e65..18aaadaeacc4ea 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -38,9 +38,7 @@
__cpp_lib_atomic_wait 201907L [C++20]
__cpp_lib_barrier 201907L [C++20]
__cpp_lib_bind_back 202202L [C++23]
- 202306L [C++26]
__cpp_lib_bind_front 201907L [C++20]
- 202306L [C++26]
__cpp_lib_bit_cast 201806L [C++20]
__cpp_lib_bitops 201907L [C++20]
__cpp_lib_bitset 202306L [C++26]
@@ -4465,17 +4463,11 @@
# endif
# endif
-# if !defined(_LIBCPP_VERSION)
-# ifndef __cpp_lib_bind_back
-# error "__cpp_lib_bind_back should be defined in c++23"
-# endif
-# if __cpp_lib_bind_back != 202202L
-# error "__cpp_lib_bind_back should have the value 202202L in c++23"
-# endif
-# else // _LIBCPP_VERSION
-# ifdef __cpp_lib_bind_back
-# error "__cpp_lib_bind_back should not be defined because it is unimplemented in libc++!"
-# endif
+# ifndef __cpp_lib_bind_back
+# error "__cpp_lib_bind_back should be defined in c++23"
+# endif
+# if __cpp_lib_bind_back != 202202L
+# error "__cpp_lib_bind_back should have the value 202202L in c++23"
# endif
# ifndef __cpp_lib_bind_front
@@ -6053,24 +6045,18 @@
# endif
# endif
-# if !defined(_LIBCPP_VERSION)
-# ifndef __cpp_lib_bind_back
-# error "__cpp_lib_bind_back should be defined in c++26"
-# endif
-# if __cpp_lib_bind_back != 202306L
-# error "__cpp_lib_bind_back should have the value 202306L in c++26"
-# endif
-# else // _LIBCPP_VERSION
-# ifdef __cpp_lib_bind_back
-# error "__cpp_lib_bind_back should not be defined because it is unimplemented in libc++!"
-# endif
+# ifndef __cpp_lib_bind_back
+# error "__cpp_lib_bind_back should be defined in c++26"
+# endif
+# if __cpp_lib_bind_back != 202202L
+# error "__cpp_lib_bind_back should have the value 202202L in c++26"
# endif
# ifndef __cpp_lib_bind_front
# error "__cpp_lib_bind_front should be defined in c++26"
# endif
-# if __cpp_lib_bind_front != 202306L
-# error "__cpp_lib_bind_front should have the value 202306L in c++26"
+# if __cpp_lib_bind_front != 201907L
+# error "__cpp_lib_bind_front should have the value 201907L in c++26"
# endif
# ifndef __cpp_lib_bit_cast
diff --git a/libcxx/test/std/utilities/function.objects/func.bind.partial/bind_back.pass.cpp b/libcxx/test/std/utilities/function.objects/func.bind.partial/bind_back.pass.cpp
new file mode 100644
index 00000000000000..aac1bd63a54cbe
--- /dev/null
+++ b/libcxx/test/std/utilities/function.objects/func.bind.partial/bind_back.pass.cpp
@@ -0,0 +1,356 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <functional>
+
+// template<class F, class... Args>
+// constexpr unspecified bind_back(F&& f, Args&&... args);
+
+#include <functional>
+
+#include <cassert>
+#include <tuple>
+#include <utility>
+
+#include "callable_types.h"
+#include "types.h"
+
+template <class Fn, class... Args>
+concept back_bindable =
+ requires(Fn&& fn, Args&&... args) { std::bind_back(std::forward<Fn>(fn), std::forward<Args>(args)...); };
+
+constexpr bool test() {
+ // Bind arguments, call without arguments
+ {
+ {
+ auto f = std::bind_back(MakeTuple{});
+ assert(f() == std::make_tuple());
+ }
+ {
+ auto f = std::bind_back(MakeTuple{}, Elem<1>{});
+ assert(f() == std::make_tuple(Elem<1>{}));
+ }
+ {
+ auto f = std::bind_back(MakeTuple{}, Elem<1>{}, Elem<2>{});
+ assert(f() == std::make_tuple(Elem<1>{}, Elem<2>{}));
+ }
+ {
+ auto f = std::bind_back(MakeTuple{}, Elem<1>{}, Elem<2>{}, Elem<3>{});
+ assert(f() == std::make_tuple(Elem<1>{}, Elem<2>{}, Elem<3>{}));
+ }
+ }
+
+ // Bind no arguments, call with arguments
+ {
+ {
+ auto f = std::bind_back(MakeTuple{});
+ assert(f(Elem<1>{}) == std::make_tuple(Elem<1>{}));
+ }
+ {
+ auto f = std::bind_back(MakeTuple{});
+ assert(f(Elem<1>{}, Elem<2>{}) == std::make_tuple(Elem<1>{}, Elem<2>{}));
+ }
+ {
+ auto f = std::bind_back(MakeTuple{});
+ assert(f(Elem<1>{}, Elem<2>{}, Elem<3>{}) == std::make_tuple(Elem<1>{}, Elem<2>{}, Elem<3>{}));
+ }
+ }
+
+ // Bind arguments, call with arguments
+ {
+ {
+ auto f = std::bind_back(MakeTuple{}, Elem<1>{});
+ assert(f(Elem<10>{}) == std::make_tuple(Elem<10>{}, Elem<1>{}));
+ }
+ {
+ auto f = std::bind_back(MakeTuple{}, Elem<1>{}, Elem<2>{});
+ assert(f(Elem<10>{}) == std::make_tuple(Elem<10>{}, Elem<1>{}, Elem<2>{}));
+ }
+ {
+ auto f = std::bind_back(MakeTuple{}, Elem<1>{}, Elem<2>{}, Elem<3>{});
+ assert(f(Elem<10>{}) == std::make_tuple(Elem<10>{}, Elem<1>{}, Elem<2>{}, Elem<3>{}));
+ }
+
+ {
+ auto f = std::bind_back(MakeTuple{}, Elem<1>{});
+ assert(f(Elem<10>{}, Elem<11>{}) == std::make_tuple(Elem<10>{}, Elem<11>{}, Elem<1>{}));
+ }
+ {
+ auto f = std::bind_back(MakeTuple{}, Elem<1>{}, Elem<2>{});
+ assert(f(Elem<10>{}, Elem<11>{}) == std::make_tuple(Elem<10>{}, Elem<11>{}, Elem<1>{}, Elem<2>{}));
+ }
+ {
+ auto f = std::bind_back(MakeTuple{}, Elem<1>{}, Elem<2>{}, Elem<3>{});
+ assert(f(Elem<10>{}, Elem<11>{}) == std::make_tuple(Elem<10>{}, Elem<11>{}, Elem<1>{}, Elem<2>{}, Elem<3>{}));
+ }
+ }
+
+ // Basic tests with fundamental types
+ {
+ int n = 2;
+ int m = 1;
+ auto add = [](int x, int y) { return x + y; };
+ auto addN = [](int a, int b, int c, int d, int e, int f) { return a + b + c + d + e + f; };
+
+ auto a = std::bind_back(add, m, n);
+ assert(a() == 3);
+
+ auto b = std::bind_back(addN, m, n, m, m, m, m);
+ assert(b() == 7);
+
+ auto c = std::bind_back(addN, n, m);
+ assert(c(1, 1, 1, 1) == 7);
+
+ auto f = std::bind_back(add, n);
+ assert(f(3) == 5);
+
+ auto g = std::bind_back(add, n, 1);
+ assert(g() == 3);
+
+ auto h = std::bind_back(addN, 1, 1, 1);
+ assert(h(2, 2, 2) == 9);
+ }
+
+ // Make sure we don't treat std::reference_wrapper specially.
+ {
+ auto sub = [](std::reference_wrapper<int> a, std::reference_wrapper<int> b) { return a.get() - b.get(); };
+ int i = 1, j = 2;
+ auto f = std::bind_back(sub, std::ref(i));
+ assert(f(std::ref(j)) == 2 - 1);
+ }
+
+ // Make sure we can call a function that's a pointer to a member function.
+ {
+ struct MemberFunction {
+ constexpr bool foo(int, int) { return true; }
+ };
+ MemberFunction value;
+ auto fn = std::bind_back(&MemberFunction::foo, 0, 0);
+ assert(fn(value));
+ }
+
+ // Make sure that we copy the bound arguments into the unspecified-type.
+ {
+ auto add = [](int x, int y) { return x + y; };
+ int n = 2;
+ auto i = std::bind_back(add, n, 1);
+ n = 100;
+ assert(i() == 3);
+ }
+
+ // Make sure we pass the bound arguments to the function object
+ // with the right value category.
+ {
+ {
+ auto wasCopied = [](CopyMoveInfo info) { return info.copy_kind == CopyMoveInfo::copy; };
+ CopyMoveInfo info;
+ auto copied = std::bind_back(wasCopied, info);
+ assert(copied());
+ }
+
+ {
+ auto wasMoved = [](CopyMoveInfo info) { return info.copy_kind == CopyMoveInfo::move; };
+ CopyMoveInfo info;
+ auto moved = std::bind_back(wasMoved, info);
+ assert(std::move(moved)());
+ }
+ }
+
+ // Make sure we call the correctly cv-ref qualified operator() based on the
+ // value category of the bind_back unspecified-type.
+ {
+ struct F {
+ constexpr int operator()() & { return 1; }
+ constexpr int operator()() const& { return 2; }
+ constexpr int operator()() && { return 3; }
+ constexpr int operator()() const&& { return 4; }
+ };
+ auto x = std::bind_back(F{});
+ using X = decltype(x);
+ assert(static_cast<X&>(x)() == 1);
+ assert(static_cast<X const&>(x)() == 2);
+ assert(static_cast<X&&>(x)() == 3);
+ assert(static_cast<X const&&>(x)() == 4);
+ }
+
+ // Make sure the bind_back unspecified-type is NOT invocable when the call would select a
+ // differently-qualified operator().
+ //
+ // For example, if the call to `operator()() &` is ill-formed, the call to the unspecified-type
+ // should be ill-formed and not fall back to the `operator()() const&` overload.
+ { // Make sure we delete the & overload when the underlying call isn't valid
+ {
+ struct F {
+ void operator()() & = delete;
+ ...
[truncated]
|
libcxx/test/std/utilities/function.objects/func.bind.partial/bind_back.pass.cpp
Outdated
Show resolved
Hide resolved
Implement `std::bind_back` function from P2387R3 "Pipe support for user-defined range adaptors".
64350bd
to
dcda573
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the patch! I have some comments but this is looking pretty good.
auto p = std::bind_back(pass, 1); | ||
static_assert(p() == 1); // expected-error {{static assertion expression is not an integral constant expression}} | ||
|
||
auto d = std::bind_back(do_nothing, 2); // expected-error {{no matching function for call to 'bind_back'}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this test checking? You can't pass an overloaded function as an argument. Am I missing something, or this test isn't testing anything from the library?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test checks if there exists some (incorrect) overload of std::bind_back
. I'm going to add comment with clarification (commit 50d4023).
You can't pass an overloaded function as an argument.
You can do something like this:
namespace std {
template<class F, class... Args>
auto bind_back(F&&, Args&&...);
void bind_back(int (*)(int));
}
template<class T>
T do_nothing(T t) {
return t;
}
void use() {
std::bind_back(do_nothing);
}
BTW, I've copied this test from bind_front.verify.cpp
:
llvm-project/libcxx/test/std/utilities/function.objects/func.bind_front/bind_front.verify.cpp
Line 42 in 1c3b15e
auto d = std::bind_front(do_nothing, n); // expected-error {{no matching function for call to 'bind_front'}} |
|
||
void test() { | ||
{ // Various failures | ||
auto p = std::bind_back(pass, 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's fundamental that pass
is an actual function (and not a function object), I would mention it in a comment and I would define pass
in this test file so we can see its definition immediately.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#include "callable_types.h" | ||
#include "types.h" | ||
|
||
constexpr void test_basic_bindings() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have any test that we can return e.g. a reference from the function and it won't get decayed? I couldn't find any, but maybe I missed them.
If we don't have any, we should also add a similar test for bind_front
while we're at it, it's pretty easy to test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
Addresses (maybe) llvm#81055 (comment)
This comment was marked as outdated.
This comment was marked as outdated.
Thanks for the patch! I'll merge now since it's green. |
Implement
std::bind_back
function from P2387R3 "Pipe support for user-defined range adaptors".