Message ID | 20240112200909.2649164-1-ppalka@redhat.com |
---|---|
State | New |
Headers | show |
Series | [1/2] libstdc++: Use C++23 deducing this in std::bind_front | expand |
On Fri, 12 Jan 2024 at 20:09, Patrick Palka <ppalka@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 >
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 }