125 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++1410 11// UNSUPPORTED: libcpp-has-no-incomplete-pstl12 13// <numeric>14 15// template<class ExecutionPolicy,16// class ForwardIterator1, class ForwardIterator2, class T>17// T transform_reduce(ExecutionPolicy&& exec,18// ForwardIterator1 first1, ForwardIterator1 last1,19// ForwardIterator2 first2,20// T init);21//22// template<class ExecutionPolicy,23// class ForwardIterator1, class ForwardIterator2, class T,24// class BinaryOperation1, class BinaryOperation2>25// T transform_reduce(ExecutionPolicy&& exec,26// ForwardIterator1 first1, ForwardIterator1 last1,27// ForwardIterator2 first2,28// T init,29// BinaryOperation1 binary_op1,30// BinaryOperation2 binary_op2);31 32#include <numeric>33#include <vector>34 35#include "MoveOnly.h"36#include "test_execution_policies.h"37#include "test_iterators.h"38#include "test_macros.h"39#include "type_algorithms.h"40 41template <class T>42struct constructible_from {43 T v_;44 45 explicit constructible_from(T v) : v_(v) {}46 47 friend constructible_from operator+(constructible_from lhs, constructible_from rhs) {48 return constructible_from{lhs.get() + rhs.get()};49 }50 51 T get() const { return v_; }52};53 54template <class Iter1, class Iter2, class ValueT>55struct Test {56 template <class Policy>57 void operator()(Policy&& policy) {58 for (const auto& pair : {std::pair{0, 34}, {1, 40}, {2, 48}, {100, 10534}, {350, 124284}}) {59 auto [size, expected] = pair;60 std::vector<int> a(size);61 std::vector<int> b(size);62 for (int i = 0; i != size; ++i) {63 a[i] = i + 1;64 b[i] = i + 4;65 }66 67 decltype(auto) ret = std::transform_reduce(68 policy,69 Iter1(std::data(a)),70 Iter1(std::data(a) + std::size(a)),71 Iter2(std::data(b)),72 ValueT(34),73 std::plus{},74 [](ValueT i, ValueT j) { return i + j + 1; });75 static_assert(std::is_same_v<decltype(ret), ValueT>);76 assert(ret == expected);77 }78 79 for (const auto& pair : {std::pair{0, 34}, {1, 30}, {2, 24}, {100, 313134}, {350, 14045884}}) {80 auto [size, expected] = pair;81 std::vector<int> a(size);82 std::vector<int> b(size);83 for (int i = 0; i != size; ++i) {84 a[i] = i + 1;85 b[i] = i - 4;86 }87 88 decltype(auto) ret = std::transform_reduce(89 policy, Iter1(std::data(a)), Iter1(std::data(a) + std::size(a)), Iter2(std::data(b)), 34);90 static_assert(std::is_same_v<decltype(ret), int>);91 assert(ret == expected);92 }93 {94 int a[] = {1, 2, 3, 4, 5, 6, 7, 8};95 int b[] = {8, 7, 6, 5, 4, 3, 2, 1};96 97 auto ret = std::transform_reduce(98 policy,99 Iter1(std::begin(a)),100 Iter1(std::end(a)),101 Iter2(std::begin(b)),102 constructible_from<int>{0},103 std::plus{},104 [](int i, int j) { return constructible_from<int>{i + j}; });105 assert(ret.get() == 72);106 }107 }108};109 110int main(int, char**) {111 types::for_each(112 types::forward_iterator_list<int*>{}, types::apply_type_identity{[](auto v) {113 using Iter2 = typename decltype(v)::type;114 types::for_each(115 types::forward_iterator_list<int*>{}, types::apply_type_identity{[](auto v2) {116 using Iter1 = typename decltype(v2)::type;117 types::for_each(118 types::type_list<int, MoveOnly>{},119 TestIteratorWithPolicies<types::partial_instantiation<Test, Iter1, Iter2>::template apply>{});120 }});121 }});122 123 return 0;124}125