https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94696
Bug ID: 94696 Summary: std::search with a parallel policy calls predicate with wrong argument types Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: schlong at cock dot li Target Milestone: --- Created attachment 48325 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=48325&action=edit search with parallel execution policy When `std::search` is called with a parallel execution policy (`std::execution::par`, `std::execution::par_unseq`, `std::execution::unseq`) and a binary predicate as the compare function, it tries to invoke the predicate with wrong argument types. ``` // snippet is also attached as a file to the bug report #include <algorithm> #include <execution> struct A{}; struct B{}; bool fn(A, B) { return true; } int main() { A a[1]{}; B b[1]{}; std::search(std::execution::par, a, a + 1, b, b + 1, fn); } ``` Compile with ``` g++ -std=c++20 ``` or c++2a if using an older version of gcc (Error also occurs in older versions of gcc). gcc -v ``` Target: x86_64-linux-gnu Configured with: ../gcc-trunk-20200421/configure --prefix=/opt/compiler-explorer/gcc-build/staging --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --disable-bootstrap --enable-multiarch --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --enable-clocale=gnu --enable-languages=c,c++,fortran,ada,d --enable-ld=yes --enable-gold=yes --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-linker-build-id --enable-lto --enable-plugins --enable-threads=posix --with-pkgversion=Compiler-Explorer-Build Thread model: posix Supported LTO compression algorithms: zlib gcc version 10.0.1 20200420 (experimental) (Compiler-Explorer-Build) ``` Output ``` In file included from /opt/compiler-explorer/gcc-trunk-20200421/include/c++/10.0.1/algorithm:61, from <source>:2: /opt/compiler-explorer/gcc-trunk-20200421/include/c++/10.0.1/bits/stl_algobase.h: In instantiation of 'constexpr bool std::equal(_IIter1, _IIter1, _IIter2, _BinaryPredicate) [with _IIter1 = B*; _IIter2 = A*; _BinaryPredicate = bool (*)(A, B)]': /opt/compiler-explorer/gcc-trunk-20200421/include/c++/10.0.1/pstl/algorithm_impl.h:449:22: required from 'bool __pstl::__internal::__brick_equal(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _BinaryPredicate, std::false_type) [with _ForwardIterator1 = B*; _ForwardIterator2 = A*; _BinaryPredicate = bool (*)(A, B); std::false_type = std::integral_constant<bool, false>]' /opt/compiler-explorer/gcc-trunk-20200421/include/c++/10.0.1/pstl/algorithm_impl.h:571:38: required from '_RandomAccessIterator1 __pstl::__internal::__find_subrange(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, _RandomAccessIterator2, _BinaryPredicate, bool, _IsVector) [with _RandomAccessIterator1 = A*; _RandomAccessIterator2 = B*; _BinaryPredicate = bool (*)(A, B); _IsVector = std::integral_constant<bool, false>]' /opt/compiler-explorer/gcc-trunk-20200421/include/c++/10.0.1/pstl/algorithm_impl.h:780:55: required from '_ForwardIterator1 __pstl::__internal::__pattern_search(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, _BinaryPredicate, _IsVector, std::true_type) [with _ExecutionPolicy = const __pstl::execution::v1::parallel_policy&; _ForwardIterator1 = A*; _ForwardIterator2 = B*; _BinaryPredicate = bool (*)(A, B); _IsVector = std::integral_constant<bool, false>; std::true_type = std::integral_constant<bool, true>]' /opt/compiler-explorer/gcc-trunk-20200421/include/c++/10.0.1/pstl/glue_algorithm_impl.h:214:40: required from '__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> std::search(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, _BinaryPredicate) [with _ExecutionPolicy = const __pstl::execution::v1::parallel_policy&; _ForwardIterator1 = A*; _ForwardIterator2 = B*; _BinaryPredicate = bool (*)(A, B); __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> = A*]' <source>:21:7: required from here /opt/compiler-explorer/gcc-trunk-20200421/include/c++/10.0.1/bits/stl_algobase.h:1437:25: error: could not convert '* __first1' from 'B' to 'A' 1437 | if (!bool(__binary_pred(*__first1, *__first2))) | ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~ | | | B Compiler returned: 1 ``` The snippet compiles with MSVC v19.24. The snippet compiles when not using an execution policy. The snippet compiles when using `std::execution::seq`.