aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2025-12-05 12:14:23 -0500
committerPatrick Palka <ppalka@redhat.com>2025-12-05 12:14:23 -0500
commit756e32a160ed353709b70e36c32edb5edffc0865 (patch)
tree08661ccfa5002df4c9cd4624f5c8dc2bbe040299
parent101f96847629850edbdfceb11b363770be4fd69d (diff)
downloadgcc-756e32a160ed353709b70e36c32edb5edffc0865.zip
gcc-756e32a160ed353709b70e36c32edb5edffc0865.tar.gz
gcc-756e32a160ed353709b70e36c32edb5edffc0865.tar.bz2
libstdc++: Use deducing this in std::not_fn when available [PR111327]
Implement the perfect forwarding required by std::not_fn using deducing this when available, instead of needing 8 operator() overloads. This also fixes Jiang An's test from this PR which would be messy to fix in the old implementation. PR libstdc++/111327 libstdc++-v3/ChangeLog: * include/std/functional (_Not_fn::operator()) [_GLIBCXX_EXPLICIT_THIS_PARAMETER]: Define as a single overload using deducing this. * testsuite/20_util/function_objects/not_fn/111327.cc: Extend test. Reviewed-by: Tomasz KamiƄski <tkaminsk@redhat.com> Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
-rw-r--r--libstdc++-v3/include/std/functional16
-rw-r--r--libstdc++-v3/testsuite/20_util/function_objects/not_fn/111327.cc19
2 files changed, 32 insertions, 3 deletions
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
index 1928a27..69a3910 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -1056,6 +1056,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Not_fn(_Not_fn&& __fn) = default;
~_Not_fn() = default;
+#if _GLIBCXX_EXPLICIT_THIS_PARAMETER
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wc++23-extensions" // deducing this
+ template<typename _Self, typename... _Args>
+ _GLIBCXX20_CONSTEXPR
+ decltype(_S_not<__inv_res_t<__like_t<_Self, _Fn>, _Args...>>())
+ operator()(this _Self&& __self, _Args&&... __args)
+ noexcept(__is_nothrow_invocable<__like_t<_Self, _Fn>, _Args...>::value
+ && noexcept(_S_not<__inv_res_t<__like_t<_Self, _Fn>, _Args...>>()))
+ {
+ return !std::__invoke(__like_t<_Self, _Not_fn>(__self)._M_fn,
+ std::forward<_Args>(__args)...);
+ }
+# pragma GCC diagnostic pop
+#else
// Macro to define operator() with given cv-qualifiers ref-qualifiers,
// forwarding _M_fn and the function arguments with the same qualifiers,
// and deducing the return type and exception-specification.
@@ -1081,6 +1096,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_NOT_FN_CALL_OP( && )
_GLIBCXX_NOT_FN_CALL_OP( const && )
#undef _GLIBCXX_NOT_FN_CALL_OP
+#endif
private:
_Fn _M_fn;
diff --git a/libstdc++-v3/testsuite/20_util/function_objects/not_fn/111327.cc b/libstdc++-v3/testsuite/20_util/function_objects/not_fn/111327.cc
index 725a842..be58b0e 100644
--- a/libstdc++-v3/testsuite/20_util/function_objects/not_fn/111327.cc
+++ b/libstdc++-v3/testsuite/20_util/function_objects/not_fn/111327.cc
@@ -15,15 +15,28 @@ struct G {
bool operator()(...) const &&;
};
+struct Weird {
+ void operator()();
+ bool operator()() const { return true; }
+};
+
int main() {
auto f = std::not_fn(F{});
- f(); // { dg-error "deleted" }
+ f(); // { dg-error "no match" }
std::move(f)();
std::as_const(f)();
std::move(std::as_const(f))();
auto g = std::not_fn(G{});
- g(); // { dg-error "deleted" }
- std::move(g)(); // { dg-error "deleted" }
+ g(); // { dg-error "no match" }
+ std::move(g)(); // { dg-error "no match" }
std::move(std::as_const(g))();
+
+ auto h = std::not_fn(Weird{});
+ h(); // { dg-error "no match" }
}
+
+// { dg-error "no type named 'type' in 'struct std::__invoke_result<" "" { target *-*-* } 0 }
+// { dg-error "no matching function for call to 'std::_Not_fn<Weird>" "" { target *-*-* } 0 }
+// { dg-error "could not convert 'std::declval<void>\\(\\)' from 'void' to 'bool'" "" { target *-*-* } 0 }
+// { dg-error "in argument to unary !" "" { target *-*-* } 0 }