On Thu, 12 Jun 2025, 16:56 Patrick Palka, <ppa...@redhat.com> wrote: > Tested on x86_64-pc-linux-gnu, does this look OK for trunk? > > I'm sure if introducing a new overload is preferable to > introducing a constexpr if branch in the existing overload. >
I think a constexpr if branch in the existing functions is cheaper. We need to check the traits either way, but we can avoid doing overload resolution. > -- >8 -- > > When composing a comparator/predicate and projection function, if both > are stateless (and default constructible) then we don't need to capture > them by reference; we can just return a captureless lambda and materialize > them on the spot. > > libstdc++-v3/ChangeLog: > > * include/bits/ranges_algo.h (__detail::__make_comp_proj): New > more specialized overload returning a stateless lambda if both > the comparator/predicate and projection are stateless. > (__detail::__make_pred_proj): Likewise. > --- > libstdc++-v3/include/bits/ranges_algo.h | 27 +++++++++++++++++++++++++ > 1 file changed, 27 insertions(+) > > diff --git a/libstdc++-v3/include/bits/ranges_algo.h > b/libstdc++-v3/include/bits/ranges_algo.h > index 819316fa79c3..7dc84d639fbd 100644 > --- a/libstdc++-v3/include/bits/ranges_algo.h > +++ b/libstdc++-v3/include/bits/ranges_algo.h > @@ -61,6 +61,21 @@ namespace ranges > }; > } > > + template<typename _Comp, typename _Proj> > + requires is_empty_v<_Comp> && is_default_constructible_v<_Comp> > + && is_empty_v<_Proj> && is_default_constructible_v<_Proj> > + constexpr auto > + __make_comp_proj(_Comp& __comp, _Proj& __proj) > + { > + return [] (auto&& __lhs, auto&& __rhs) -> bool { > + using _TL = decltype(__lhs); > + using _TR = decltype(__rhs); > + return std::__invoke(_Comp{}, > + std::__invoke(_Proj{}, > std::forward<_TL>(__lhs)), > + std::__invoke(_Proj{}, > std::forward<_TR>(__rhs))); > + }; > + } > + > template<typename _Pred, typename _Proj> > constexpr auto > __make_pred_proj(_Pred& __pred, _Proj& __proj) > @@ -70,6 +85,18 @@ namespace ranges > std::__invoke(__proj, > std::forward<_Tp>(__arg))); > }; > } > + > + template<typename _Pred, typename _Proj> > + requires is_empty_v<_Pred> && is_default_constructible_v<_Pred> > + && is_empty_v<_Proj> && is_default_constructible_v<_Pred> > + constexpr auto > + __make_pred_proj(_Pred& __pred, _Proj& __proj) > + { > + return [] <typename _Tp> (_Tp&& __arg) -> bool { > + return std::__invoke(_Pred{}, > + std::__invoke(_Proj{}, > std::forward<_Tp>(__arg))); > + }; > + } > } // namespace __detail > > struct __all_of_fn > -- > 2.50.0.rc2 > >