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