https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104251
Bug ID: 104251 Summary: std::reduce scrambles argument order for BinaryOp function call: Possible bug? Product: gcc Version: 11.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: felix.koehler at gmail dot com Target Milestone: --- Created attachment 52298 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=52298&action=edit Disable testcase test03 to compile with GCC I experimented with std::reduce from the libstdc++ library and I get completely different results for all slightly non-trivial cases comparing CLANG-13.0.0/CLANG-HEAD-14.0.0 output vs GCC--10.2.0/11.1.0/HEAD 12.0.1 20220123 (experimental). (Using wandbox.org) a) the arguments with a non-default BinOp parameter seem to get scrambled, see attachment test01(). vector<int> x={1,2,3,1}; int sum; auto b=x.cbegin(); auto e=x.cend(); cout << reduce(b, e, 0, [](int sum, int i) {return sum+i+i;}) << "\t"; yields 14 for CLANG, 30 for GCC. Trace of the lambda function calls included in the attachment. b) Even a simple double addition lambda function does not work, if the accumulator value requires a higher precision to hold the result, than can be stored in the type of the sequence to be reduced. See attachment test02(). This is probably not the intended behavior. vector<unsigned char>bytes = {200, 201, 202, 203}; cout << reduce(bytes.begin(), bytes.end(), 0L, [](long sum, unsigned char i) {return sum+i;}); yields the expected 806 for CLANG, GCC overflows and yields 38. c) Using non-implicitely-convertible types for the accumulator and the reduced function is not supported in GCC, yet CLANG compiles and runs the following code just fine. See test03(). TLDR: vector<string> numbers={"eins","dos", "three", "quatre"}; cout << reduce(numbers.begin(), numbers.end(), 0L, [](size_t sum, string s) {return sum+s.size();}) << "\t"; CLANG counts 18 letters, GCC refuses compilation with an error message that the init value 0L cannot be converted into the sequence type of string. According to cppreference.com: "The behavior is non-deterministic if binary_op is not associative or not commutative. ... in other words, reduce behaves like std::accumulate except the elements of the range may be grouped and rearranged in arbitrary order." which seems to support the CLANG interpretation. I'm not a language lawyer, GCC might be correct in assuming that the sequence MUST have the same type as the result of the reduce function and you cannot expect to get passed the accumulator value as the first argument to BinOp and the sequence value as the second argument. However, this reduces std::reduce to a trivial SUM/PRODUCT function with a horrible interface and really evil implicit type-casting traps. This seems to be a bug in either the libstdc++ implementation or the standard itself, please correct me, if I'm wrong.