wash added a comment. Suppose you have:
struct A {}; struct B {}; A operator+(A, B); std::vector<B> v; std::reduce(v.begin(), v.end(), A{}); The implementation in this patch works fine for the above case - as would `accumulate`, which it is equivalent to. However, `reduce` requires that "All of `binary_op(init, *first)`, `binary_op(*first, init)`, `binary_op(init, init)`, and `binary_op(*first, *first)` shall be convertible to T.", as all those operations may be needed for the parallel execution-policy overload of `reduce` (the requirement applies to the non-execution-policy overload as well). E.g. in the above example, these operations are also required by `reduce`, even though the non-parallel implementation does not need them: A operator+(B, A); A operator+(A, A); A operator+(B, B); Should the non-parallel implementation of `reduce` static_assert or SFINAE away when these requirements are not met? I think it might be desirable to ensure that if this won't compile: std::reduce(std::par, v.begin(), v.end(), A{}); Then this will also not compile: std::reduce(v.begin(), v.end(), A{}); (And the spec seems to suggest this too). ================ Comment at: include/numeric:154 + return reduce(__first, __last, + typename iterator_traits<_InputIterator>::value_type{}, _VSTD::plus<>()); +} ---------------- In the spec, this overload of `reduce` is described as equivalent to `return reduce(std::forward<ExecutionPolicy>(exec), first, last, typename iterator_traits<ForwardIterator>::value_type{});`. The overload that it calls (the three argument version that omits a binary operation) just forwards to the four-argument reduce, adding the `plus<>()` argument. Is there a reason you wanted to avoid the extra layer of function call indirection (it should be inlined and optimized away, right)? What you have seems perfectly fine, I'm just curious though. ================ Comment at: test/std/numerics/numeric.ops/reduce/reduce_iter_iter.pass.cpp:37 + unsigned sa = sizeof(ia) / sizeof(ia[0]); + test(Iter(ia), Iter(ia), 0); + test(Iter(ia), Iter(ia+1), 1); ---------------- Just to confirm, this should be 0 because the "default" init value is `iterator_traits<_InputIterator>::value_type{}`, and `int{}` gives you a determinate result (as opposed to `int()` which would not), correct? https://reviews.llvm.org/D33997 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits