On Tue, 12 Sept 2023 at 02:11, Patrick Palka via Libstdc++ <libstd...@gcc.gnu.org> wrote: > > The previous patch fixed perfect forwarding for std::bind_front. > This patch fixes the same issue for std::not_fn. > > Tested on x86_64-pc-linux-gnu, does this look OK for trunk and > perhaps 13?
Yes for both, thanks. > > PR libstdc++/111327 > > libstdc++-v3/ChangeLog: > > * include/std/functional (_GLIBCXX_NOT_FN_CALL_OP): Also define > a deleted fallback operator() overload. Constrain both the > main and deleted overloads accordingly. > * testsuite/20_util/function_objects/not_fn/111327.cc: New test. > --- > libstdc++-v3/include/std/functional | 10 +++++-- > .../20_util/function_objects/not_fn/111327.cc | 29 +++++++++++++++++++ > 2 files changed, 37 insertions(+), 2 deletions(-) > create mode 100644 > libstdc++-v3/testsuite/20_util/function_objects/not_fn/111327.cc > > diff --git a/libstdc++-v3/include/std/functional > b/libstdc++-v3/include/std/functional > index c50b9e4d365..9551e38dfdb 100644 > --- a/libstdc++-v3/include/std/functional > +++ b/libstdc++-v3/include/std/functional > @@ -1061,7 +1061,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > // forwarding _M_fn and the function arguments with the same > qualifiers, > // and deducing the return type and exception-specification. > #define _GLIBCXX_NOT_FN_CALL_OP( _QUALS ) \ > - template<typename... _Args> \ > + template<typename... _Args, \ > + typename = enable_if_t<__is_invocable<_Fn _QUALS, > _Args...>::value>> \ > _GLIBCXX20_CONSTEXPR \ > decltype(_S_not<__inv_res_t<_Fn _QUALS, _Args...>>()) \ > operator()(_Args&&... __args) _QUALS \ > @@ -1070,7 +1071,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > { \ > return !std::__invoke(std::forward< _Fn _QUALS >(_M_fn), \ > std::forward<_Args>(__args)...); \ > - } > + } \ > + \ > + template<typename... _Args, \ > + typename = enable_if_t<!__is_invocable<_Fn _QUALS, > _Args...>::value>> \ > + void operator()(_Args&&... __args) _QUALS = delete; > + > _GLIBCXX_NOT_FN_CALL_OP( & ) > _GLIBCXX_NOT_FN_CALL_OP( const & ) > _GLIBCXX_NOT_FN_CALL_OP( && ) > 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 > new file mode 100644 > index 00000000000..93e00ee8057 > --- /dev/null > +++ b/libstdc++-v3/testsuite/20_util/function_objects/not_fn/111327.cc > @@ -0,0 +1,29 @@ > +// PR libstdc++/111327 - std::bind_front (and std::not_fn) doesn't perfectly > +// forward according to value category of the call wrapper object > +// { dg-do compile { target c++17 } } > + > +#include <functional> > +#include <utility> > + > +struct F { > + void operator()(...) & = delete; > + bool operator()(...) const &; > +}; > + > +struct G { > + void operator()(...) && = delete; > + bool operator()(...) const &&; > +}; > + > +int main() { > + auto f = std::not_fn(F{}); > + f(); // { dg-error "deleted" } > + 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" } > + std::move(std::as_const(g))(); > +} > -- > 2.42.0.158.g94e83dcf5b >