From: Patrick Palka <ppalka@redhat.com>
To: gcc-patches@gcc.gnu.org
Cc: libstdc++@gcc.gnu.org, Patrick Palka <ppalka@redhat.com>
Subject: [PATCH 2/3] libstdc++: Fix std::bind_front perfect forwarding [PR111327]
Date: Mon, 11 Sep 2023 21:08:51 -0400 [thread overview]
Message-ID: <20230912010852.1027184-2-ppalka@redhat.com> (raw)
In-Reply-To: <20230912010852.1027184-1-ppalka@redhat.com>
In order to properly implement a perfect forwarding call wrapper
(before 'deducing this' at least) we need a total of 8 operator()
overloads, 4 main ones and 4 deleted ones for each const/ref qual pair,
as described in section 5.5 of P0847R6. Otherwise the wrapper may
not perfectly forward according to the value category and constness
of the wrapped object. This patch fixes this bug in std::bind_front.
PR libstdc++/111327
libstdc++-v3/ChangeLog:
* include/std/functional (_Bind_front::operator()): Add deleted
fallback overloads for each const/ref qualifier pair. Give the
main overloads dummy constraints to make them more specialized
than the deleted overloads.
* testsuite/20_util/function_objects/bind_front/111327.cc: New test.
---
libstdc++-v3/include/std/functional | 16 ++++++++
.../function_objects/bind_front/111327.cc | 41 +++++++++++++++++++
2 files changed, 57 insertions(+)
create mode 100644 libstdc++-v3/testsuite/20_util/function_objects/bind_front/111327.cc
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
index 7d1b890bb4e..c50b9e4d365 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -938,6 +938,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
~_Bind_front() = default;
template<typename... _CallArgs>
+ requires true
constexpr
invoke_result_t<_Fd&, _BoundArgs&..., _CallArgs...>
operator()(_CallArgs&&... __call_args) &
@@ -948,6 +949,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
template<typename... _CallArgs>
+ requires true
constexpr
invoke_result_t<const _Fd&, const _BoundArgs&..., _CallArgs...>
operator()(_CallArgs&&... __call_args) const &
@@ -959,6 +961,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
template<typename... _CallArgs>
+ requires true
constexpr
invoke_result_t<_Fd, _BoundArgs..., _CallArgs...>
operator()(_CallArgs&&... __call_args) &&
@@ -969,6 +972,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
template<typename... _CallArgs>
+ requires true
constexpr
invoke_result_t<const _Fd, const _BoundArgs..., _CallArgs...>
operator()(_CallArgs&&... __call_args) const &&
@@ -979,6 +983,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
std::forward<_CallArgs>(__call_args)...);
}
+ template<typename... _CallArgs>
+ void operator()(_CallArgs&&...) & = delete;
+
+ template<typename... _CallArgs>
+ void operator()(_CallArgs&&...) const & = delete;
+
+ template<typename... _CallArgs>
+ void operator()(_CallArgs&&...) && = delete;
+
+ template<typename... _CallArgs>
+ void operator()(_CallArgs&&...) const && = delete;
+
private:
using _BoundIndices = index_sequence_for<_BoundArgs...>;
diff --git a/libstdc++-v3/testsuite/20_util/function_objects/bind_front/111327.cc b/libstdc++-v3/testsuite/20_util/function_objects/bind_front/111327.cc
new file mode 100644
index 00000000000..6eb51994476
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/function_objects/bind_front/111327.cc
@@ -0,0 +1,41 @@
+// PR libstdc++/111327 - std::bind_front doesn't perfectly forward according
+// to value category of the call wrapper object
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+
+#include <functional>
+#include <utility>
+
+struct F {
+ void operator()(...) & = delete;
+ void operator()(...) const &;
+};
+
+struct G {
+ void operator()(...) && = delete;
+ void operator()(...) const &&;
+};
+
+int main() {
+ auto f0 = std::bind_front(F{});
+ f0(); // { dg-error "deleted" }
+ std::move(f0)();
+ std::as_const(f0)();
+ std::move(std::as_const(f0))();
+
+ auto g0 = std::bind_front(G{});
+ g0(); // { dg-error "deleted" }
+ std::move(g0)(); // { dg-error "deleted" }
+ std::move(std::as_const(g0))();
+
+ auto f1 = std::bind_front(F{}, 42);
+ f1(); // { dg-error "deleted" }
+ std::move(f1)();
+ std::as_const(f1)();
+ std::move(std::as_const(f1))();
+
+ auto g1 = std::bind_front(G{}, 42);
+ g1(); // { dg-error "deleted" }
+ std::move(g1)(); // { dg-error "deleted" }
+ std::move(std::as_const(g1))();
+}
--
2.42.0.158.g94e83dcf5b
next prev parent reply other threads:[~2023-09-12 1:08 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-09-12 1:08 [PATCH 1/3] libstdc++: Remove std::bind_front specialization for no bound args Patrick Palka
2023-09-12 1:08 ` Patrick Palka [this message]
2023-09-12 13:16 ` [PATCH 2/3] libstdc++: Fix std::bind_front perfect forwarding [PR111327] Jonathan Wakely
2023-09-12 1:08 ` [PATCH 3/3] libstdc++: Fix std::not_fn " Patrick Palka
2023-09-12 13:16 ` Jonathan Wakely
2023-09-12 12:46 ` [PATCH 1/3] libstdc++: Remove std::bind_front specialization for no bound args Patrick Palka
2023-09-12 13:15 ` Jonathan Wakely
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230912010852.1027184-2-ppalka@redhat.com \
--to=ppalka@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=libstdc++@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).