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
> 

Reply via email to