On Mon, 20 Jan 2025, Jonathan Wakely wrote: > > > On Monday, 20 January 2025, Patrick Palka <ppa...@redhat.com> wrote: > > 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! > > Agreed, this is ok for trunk and any relevant branches. Could you please push > this one, Patrick?
Pushed to trunk so far. > > > > > >> > >> libstdc++-v3/ChangeLog: > >> > >> PR libstdc++/118185 > >> PR libstdc++/100249 A leading tab was needed on this line in order to make the changelog/commit hook happy. > >> * 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))) I also made the trivial formatting change of splitting these lines up to be more consistent with nearby code. > >> 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 > >> > > > > >