On Sun, 19 Jan 2025, Giuseppe D'Angelo wrote: > Hi, > > the attached patch fixes PR118185 (mentioned in the earlier thread about > 118160). Tested on x86-64 Linux. > > Thanks, > -- > Giuseppe D'Angelo >
> Subject: [PATCH] libstdc++: perfectly forward std::ranges::clamp arguments > > As reported in PR118185, std::ranges::clamp does not correctly forward > the projected value to the comparator. Add the missing forward. LGTM! > > libstdc++-v3/ChangeLog: > > PR libstdc++/118185 > PR libstdc++/100249 > * include/bits/ranges_algo.h (__clamp_fn): Correctly forward the > projected value to the comparator. > * testsuite/25_algorithms/clamp/118185.cc: New test. > > Signed-off-by: Giuseppe D'Angelo <giuseppe.dang...@kdab.com> > --- > libstdc++-v3/include/bits/ranges_algo.h | 4 +- > .../testsuite/25_algorithms/clamp/118185.cc | 42 +++++++++++++++++++ > 2 files changed, 44 insertions(+), 2 deletions(-) > create mode 100644 libstdc++-v3/testsuite/25_algorithms/clamp/118185.cc > > diff --git a/libstdc++-v3/include/bits/ranges_algo.h > b/libstdc++-v3/include/bits/ranges_algo.h > index e38a330d48c..bb6ab8b6b4b 100644 > --- a/libstdc++-v3/include/bits/ranges_algo.h > +++ b/libstdc++-v3/include/bits/ranges_algo.h > @@ -2993,9 +2993,9 @@ namespace ranges > std::__invoke(__proj, __hi), > std::__invoke(__proj, __lo)))); > auto&& __proj_val = std::__invoke(__proj, __val); > - if (std::__invoke(__comp, __proj_val, std::__invoke(__proj, __lo))) > + if (std::__invoke(__comp, > std::forward<decltype(__proj_val)>(__proj_val), std::__invoke(__proj, __lo))) > return __lo; > - else if (std::__invoke(__comp, std::__invoke(__proj, __hi), __proj_val)) > + else if (std::__invoke(__comp, std::__invoke(__proj, __hi), > std::forward<decltype(__proj_val)>(__proj_val))) > return __hi; > else > return __val; > diff --git a/libstdc++-v3/testsuite/25_algorithms/clamp/118185.cc > b/libstdc++-v3/testsuite/25_algorithms/clamp/118185.cc > new file mode 100644 > index 00000000000..908eb708c1e > --- /dev/null > +++ b/libstdc++-v3/testsuite/25_algorithms/clamp/118185.cc > @@ -0,0 +1,42 @@ > +// { dg-do compile { target c++20 } } > + > +#include <algorithm> > +#include <concepts> > + > +struct Comp > +{ > + constexpr bool operator()(const int&& x, const int&& y) { return x < y; } > +}; > + > +struct Proj > +{ > + constexpr const int&& operator()(const int& x) const { return > std::move(x); } > +}; > + > +static_assert(std::indirect_strict_weak_order<Comp, std::projected<const > int*, Proj>>); > + > +static_assert(std::ranges::clamp(+1, 0, 2, Comp{}, Proj{}) == 1); > +static_assert(std::ranges::clamp(-1, 0, 2, Comp{}, Proj{}) == 0); > +static_assert(std::ranges::clamp(10, 0, 2, Comp{}, Proj{}) == 2); > + > + > +// Testcase from PR118185 > + > +struct Comp2 > +{ > + constexpr bool operator()(const int&& x, const int&& y) const { return x < > y; } > + constexpr bool operator()(const int&& x, int& y) const { return x < y; } > + constexpr bool operator()(int& x, const int&& y) const { return x < y; } > + constexpr bool operator()(int& x, int& y) const { return x < y; } > + constexpr bool operator()(std::same_as<const int&> auto && x, > std::same_as<const int&> auto && y) const > + { > + return x < y; > + } > +}; > + > +static_assert(std::indirect_strict_weak_order<Comp2, std::projected<const > int*, Proj>>); > + > +static_assert(std::ranges::clamp(+1, 0, 2, Comp2{}, Proj{}) == 1); > +static_assert(std::ranges::clamp(-1, 0, 2, Comp2{}, Proj{}) == 0); > +static_assert(std::ranges::clamp(10, 0, 2, Comp2{}, Proj{}) == 2); > + > -- > 2.34.1 >