On Fri, 12 Jan 2024 at 20:09, Patrick Palka <ppa...@redhat.com> wrote: > > This simplifies the operator() of _Bind_front using C++23 deducing > this, allowing us to condense multiple nearly identical operator() > overloads into one. > > In passing I think we can remove _Bind_front's defaulted special member > declarations and just let the compiler implicitly generate them for us.
OK > > libstdc++-v3/ChangeLog: > > * include/std/functional (_Bind_front): Remove =default special > member function declarations. > (_Bind_front::operator()): Implement using C++23 deducing this > when available. > * testsuite/20_util/function_objects/bind_front/111327.cc: > Adjust testcase to expect better errors in C++23 mode. > --- > libstdc++-v3/include/std/functional | 20 +++++++++++++------ > .../function_objects/bind_front/111327.cc | 14 +++++++------ > 2 files changed, 22 insertions(+), 12 deletions(-) > > diff --git a/libstdc++-v3/include/std/functional > b/libstdc++-v3/include/std/functional > index 8d50a730889..190cea612bb 100644 > --- a/libstdc++-v3/include/std/functional > +++ b/libstdc++-v3/include/std/functional > @@ -934,12 +934,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > _M_bound_args(std::forward<_Args>(__args)...) > { static_assert(sizeof...(_Args) == sizeof...(_BoundArgs)); } > > - _Bind_front(const _Bind_front&) = default; > - _Bind_front(_Bind_front&&) = default; > - _Bind_front& operator=(const _Bind_front&) = default; > - _Bind_front& operator=(_Bind_front&&) = default; > - ~_Bind_front() = default; > - > +#if __cpp_explicit_this_parameter > + template<typename _Self, typename... _CallArgs> > + constexpr > + invoke_result_t<__like_t<_Self, _Fd>, __like_t<_Self, _BoundArgs>..., > _CallArgs...> > + operator()(this _Self&& __self, _CallArgs&&... __call_args) > + noexcept(is_nothrow_invocable_v<__like_t<_Self, _Fd>, > + __like_t<_Self, _BoundArgs>..., > + _CallArgs...>) > + { > + return _S_call(std::forward<_Self>(__self), _BoundIndices(), > + std::forward<_CallArgs>(__call_args)...); > + } > +#else > template<typename... _CallArgs> > requires true > constexpr > @@ -997,6 +1004,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > template<typename... _CallArgs> > void operator()(_CallArgs&&...) const && = delete; > +#endif > > 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 > index 43b56ca4378..5fe0a83baec 100644 > --- a/libstdc++-v3/testsuite/20_util/function_objects/bind_front/111327.cc > +++ b/libstdc++-v3/testsuite/20_util/function_objects/bind_front/111327.cc > @@ -17,24 +17,26 @@ struct G { > > int main() { > auto f0 = std::bind_front(F{}); > - f0(); // { dg-error "deleted" } > + f0(); // { dg-error "deleted|no match" } > 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" } > + g0(); // { dg-error "deleted|no match" } > + std::move(g0)(); // { dg-error "deleted|no match" } > std::move(std::as_const(g0))(); > > auto f1 = std::bind_front(F{}, 42); > - f1(); // { dg-error "deleted" } > + f1(); // { dg-error "deleted|no match" } > 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" } > + g1(); // { dg-error "deleted|no match" } > + std::move(g1)(); // { dg-error "deleted|no match" } > std::move(std::as_const(g1))(); > } > + > +// { dg-error "no type named 'type' in 'struct std::invoke_result" "" { > target c++23 } 0 } > -- > 2.43.0.283.ga54a84b333 >