On Thu, May 22, 2025 at 1:42 PM Jonathan Wakely <jwak...@redhat.com> wrote:

> This looks to have been wrong since r0-125454-gea89b2482f97aa which
> introduced the predefined_ops.h. Since that change, the binary predicate
> passed to std::__unique_copy is _Iter_comp_iter, which takes arguments
> of the iterator type, not the iterator's value type.
>
> This removes the checks from the __unique_copy overloads and moves them
> into the second overload of std::unique_copy, where we have the original
> binary predicate, not the adapted one from predefined_ops.h.
>
> The third __unique_copy overload currently checks that the predicate is
> callable with the input range value type and the output range value
> type. This change alters that, so that we only ever check that the
> predicate can be called with two arguments of the same type. That is
> intentional, because calling the predicate with different types is a bug
> that will be fixed in a later commit (see PR libstdc++/120386).
>
> libstdc++-v3/ChangeLog:
>
>         PR libstdc++/120384
>         * include/bits/stl_algo.h (__unique_copy): Remove all
>         _BinaryPredicateConcept concept checks.
>         (unique_copy): Check _BinaryPredicateConcept in overload that
>         takes a predicate.
>         * testsuite/25_algorithms/unique_copy/120384.cc: New test.
> ---
>
> Tested x86_64-linux.
>
Took me a bit of time to understand why the check is having the same value
type
two times. But after reading the second commit, it makes sense.
LGTM, thanks.

>
>  libstdc++-v3/include/bits/stl_algo.h            | 17 +++--------------
>  .../25_algorithms/unique_copy/120384.cc         | 12 ++++++++++++
>  2 files changed, 15 insertions(+), 14 deletions(-)
>  create mode 100644
> libstdc++-v3/testsuite/25_algorithms/unique_copy/120384.cc
>
> diff --git a/libstdc++-v3/include/bits/stl_algo.h
> b/libstdc++-v3/include/bits/stl_algo.h
> index 71ead103d2bf..f5361aeab7e2 100644
> --- a/libstdc++-v3/include/bits/stl_algo.h
> +++ b/libstdc++-v3/include/bits/stl_algo.h
> @@ -932,11 +932,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>                   _OutputIterator __result, _BinaryPredicate __binary_pred,
>                   forward_iterator_tag, output_iterator_tag)
>      {
> -      // concept requirements -- iterators already checked
> -
> __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
> -         typename iterator_traits<_ForwardIterator>::value_type,
> -         typename iterator_traits<_ForwardIterator>::value_type>)
> -
>        _ForwardIterator __next = __first;
>        *__result = *__first;
>        while (++__next != __last)
> @@ -962,11 +957,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>                   _OutputIterator __result, _BinaryPredicate __binary_pred,
>                   input_iterator_tag, output_iterator_tag)
>      {
> -      // concept requirements -- iterators already checked
> -
> __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
> -         typename iterator_traits<_InputIterator>::value_type,
> -         typename iterator_traits<_InputIterator>::value_type>)
> -
>        typename iterator_traits<_InputIterator>::value_type __value =
> *__first;
>        __decltype(__gnu_cxx::__ops::__iter_comp_val(__binary_pred))
>         __rebound_pred
> @@ -995,10 +985,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>                   _ForwardIterator __result, _BinaryPredicate
> __binary_pred,
>                   input_iterator_tag, forward_iterator_tag)
>      {
> -      // concept requirements -- iterators already checked
> -
> __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
> -         typename iterator_traits<_ForwardIterator>::value_type,
> -         typename iterator_traits<_InputIterator>::value_type>)
>        *__result = *__first;
>        while (++__first != __last)
>         if (!__binary_pred(__result, __first))
> @@ -4505,6 +4491,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
>        __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
>             typename iterator_traits<_InputIterator>::value_type>)
>        __glibcxx_requires_valid_range(__first, __last);
> +
> __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
> +         typename iterator_traits<_InputIterator>::value_type,
> +         typename iterator_traits<_InputIterator>::value_type>)
>
>        if (__first == __last)
>         return __result;
> diff --git a/libstdc++-v3/testsuite/25_algorithms/unique_copy/120384.cc
> b/libstdc++-v3/testsuite/25_algorithms/unique_copy/120384.cc
> new file mode 100644
> index 000000000000..27cd3375acae
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/25_algorithms/unique_copy/120384.cc
> @@ -0,0 +1,12 @@
> +// { dg-options "-D_GLIBCXX_CONCEPT_CHECKS" }
> +// { dg-do compile }
> +
> +// PR 120384 _BinaryPredicateConcept checks in std::unique_copy are wrong
> +
> +#include <algorithm>
> +
> +void
> +test_pr120384(const int* first, const int* last, int* out)
> +{
> +  std::unique_copy(first, last, out);
> +}
> --
> 2.49.0
>
>

Reply via email to