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. 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