On Mon, Sep 8, 2025 at 8:45 AM Tomasz Kaminski <tkami...@redhat.com> wrote:

>
>
> On Fri, Sep 5, 2025 at 10:57 PM Jonathan Wakely <jwak...@redhat.com>
> wrote:
>
>> C++17 has a 'Requires:' precondition that the two random access iterator
>> types have the same value type. In C++20 that is a 'Mandates:'
>> requirement which we must diagnose.
>>
>> Although we could diagnose it in C++17, that might be a breaking change
>> for any users relying on it today. Also I am lazy and wanted to use
>> C++20's std::iter_value_t for the checks. So this only enforces the
>> requirement for C++20 and later.
>>
> Could add a word here, on the motivation for checking that. If we allow
> different
> types, we may get ones for which equality is transparent, but hashes are
> not equal
> for equivalent object of different types. One example would be
> chrono::durations,
> with different Ratios.
>
Outside of that LGTM.

>
>> libstdc++-v3/ChangeLog:
>>
>>         * include/std/functional (boyer_moore_searcher::operator()): Add
>>         static_assert.
>>         (boyer_moore_horspool_searcher::operator()): Likewise.
>>         * testsuite/20_util/function_objects/121782.cc: New test.
>> ---
>>
>> Tested powerpc64le-linux.
>>
>>  libstdc++-v3/include/std/functional           |  8 +++++
>>  .../20_util/function_objects/121782.cc        | 30 +++++++++++++++++++
>>  2 files changed, 38 insertions(+)
>>  create mode 100644
>> libstdc++-v3/testsuite/20_util/function_objects/121782.cc
>>
>> diff --git a/libstdc++-v3/include/std/functional
>> b/libstdc++-v3/include/std/functional
>> index 5b329daf184e..cc2f16b64b71 100644
>> --- a/libstdc++-v3/include/std/functional
>> +++ b/libstdc++-v3/include/std/functional
>> @@ -1256,6 +1256,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>>         operator()(_RandomAccessIterator2 __first,
>>                    _RandomAccessIterator2 __last) const
>>         {
>> +#ifdef __glibcxx_concepts // >= C++20
>> +         static_assert(is_same_v<iter_value_t<_RAIter>,
>> +                                 iter_value_t<_RandomAccessIterator2>>);
>> +#endif
>>           const auto& __pred = this->_M_pred();
>>           auto __patlen = _M_pat_end - _M_pat;
>>           if (__patlen == 0)
>> @@ -1317,6 +1321,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>>      operator()(_RandomAccessIterator2 __first,
>>                _RandomAccessIterator2 __last) const
>>      {
>> +#ifdef __glibcxx_concepts // >= C++20
>> +      static_assert(is_same_v<iter_value_t<_RAIter>,
>> +                             iter_value_t<_RandomAccessIterator2>>);
>> +#endif
>>        auto __patlen = _M_pat_end - _M_pat;
>>        if (__patlen == 0)
>>         return std::make_pair(__first, __first);
>> diff --git a/libstdc++-v3/testsuite/20_util/function_objects/121782.cc
>> b/libstdc++-v3/testsuite/20_util/function_objects/121782.cc
>> new file mode 100644
>> index 000000000000..f18fb1ef25cc
>> --- /dev/null
>> +++ b/libstdc++-v3/testsuite/20_util/function_objects/121782.cc
>> @@ -0,0 +1,30 @@
>> +// { dg-do compile { target c++17 } }
>> +// libstdc++/121782
>> +// Missing Mandates for operator() of
>> std::boyer_moore_[horspool]_searcher
>> +
>> +// N.B. we only enforce this for C++20 and later.
>> +// { dg-error "static assertion failed" "" { target c++20 } 0 }
>> +
>> +#include <algorithm>
>> +#include <functional>
>> +#include <testsuite_iterators.h>
>> +
>> +template<typename T>
>> +using Range = __gnu_test::random_access_container<T>;
>> +
>> +void
>> +test_bm(Range<char> needle, Range<unsigned char> haystack)
>> +{
>> +  std::boyer_moore_searcher s(needle.begin(), needle.end());
>> +  (void) std::search(haystack.begin(), haystack.end(), s); // { dg-error
>> "here" "" { target c++20 } }
>> +  // { dg-error "'char' is not the same as 'unsigned char'" "" { target
>> c++20 } 0 }
>> +}
>> +
>> +void
>> +test_bmh(Range<char> needle, Range<signed char> haystack)
>> +{
>> +  std::boyer_moore_horspool_searcher s(needle.begin(), needle.end());
>> +  (void) std::search(haystack.begin(), haystack.end(), s); // { dg-error
>> "here" "" { target c++20 } }
>> +  // { dg-error "'char' is not the same as 'signed char'" "" { target
>> c++20 } 0 }
>> +}
>> +
>> --
>> 2.51.0
>>
>>

Reply via email to