diff options
| author | Patrick Palka <ppalka@redhat.com> | 2025-12-05 12:14:23 -0500 |
|---|---|---|
| committer | Patrick Palka <ppalka@redhat.com> | 2025-12-05 12:14:23 -0500 |
| commit | 756e32a160ed353709b70e36c32edb5edffc0865 (patch) | |
| tree | 08661ccfa5002df4c9cd4624f5c8dc2bbe040299 | |
| parent | 101f96847629850edbdfceb11b363770be4fd69d (diff) | |
| download | gcc-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/functional | 16 | ||||
| -rw-r--r-- | libstdc++-v3/testsuite/20_util/function_objects/not_fn/111327.cc | 19 |
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 } |
