xref: /llvm-project/libcxx/test/std/numerics/numeric.ops/partial.sum/partial_sum_op.pass.cpp (revision 67c88e47bdba2578150a9034a717d6ddcace4e13)
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // <numeric>
10 // UNSUPPORTED: clang-8
11 
12 // Became constexpr in C++20
13 // template<InputIterator InIter,
14 //          OutputIterator<auto, const InIter::value_type&> OutIter,
15 //          Callable<auto, const InIter::value_type&, InIter::reference> BinaryOperation>
16 //   requires HasAssign<InIter::value_type, BinaryOperation::result_type>
17 //         && Constructible<InIter::value_type, InIter::reference>
18 //         && CopyConstructible<BinaryOperation>
19 //   OutIter
20 //   partial_sum(InIter first, InIter last, OutIter result, BinaryOperation binary_op);
21 
22 #include <numeric>
23 #include <functional>
24 #include <string>
25 #include <cassert>
26 
27 #include "test_macros.h"
28 #include "test_iterators.h"
29 
30 #if TEST_STD_VER > 17
31 struct rvalue_addable
32 {
33     bool correctOperatorUsed = false;
34 
35     // make sure the predicate is passed an rvalue and an lvalue (so check that the first argument was moved)
36     constexpr rvalue_addable operator()(rvalue_addable&& r, rvalue_addable const&) {
37         r.correctOperatorUsed = true;
38         return std::move(r);
39     }
40 };
41 
42 constexpr rvalue_addable operator+(rvalue_addable& lhs, rvalue_addable const&)
43 {
44     lhs.correctOperatorUsed = false;
45     return lhs;
46 }
47 
48 constexpr rvalue_addable operator+(rvalue_addable&& lhs, rvalue_addable const&)
49 {
50     lhs.correctOperatorUsed = true;
51     return std::move(lhs);
52 }
53 
54 constexpr void
55 test_use_move()
56 {
57     const std::size_t size = 100;
58     rvalue_addable arr[size];
59     rvalue_addable res1[size];
60     rvalue_addable res2[size];
61     std::partial_sum(arr, arr + size, res1);
62     std::partial_sum(arr, arr + size, res2, /*predicate=*/rvalue_addable());
63     // start at 1 because the first element is not moved
64     for (unsigned i = 1; i < size; ++i) assert(res1[i].correctOperatorUsed);
65     for (unsigned i = 1; i < size; ++i) assert(res2[i].correctOperatorUsed);
66 }
67 #endif // TEST_STD_VER > 17
68 
69 // C++20 can use string in constexpr evaluation, but both libc++ and MSVC
70 // don't have the support yet. In these cases omit the constexpr test.
71 // FIXME Remove constexpr string workaround introduced in D90569
72 #if TEST_STD_VER > 17 && \
73 	(!defined(__cpp_lib_constexpr_string) || __cpp_lib_constexpr_string < 201907L)
74 void
75 #else
76 TEST_CONSTEXPR_CXX20 void
77 #endif
78 test_string()
79 {
80     std::string sa[] = {"a", "b", "c"};
81     std::string sr[] = {"a", "ba", "cb"};
82     std::string output[3];
83     std::adjacent_difference(sa, sa + 3, output, std::plus<std::string>());
84     for (unsigned i = 0; i < 3; ++i) assert(output[i] == sr[i]);
85 }
86 
87 template <class InIter, class OutIter>
88 TEST_CONSTEXPR_CXX20 void
89 test()
90 {
91     int ia[] = {1, 2, 3, 4, 5};
92     int ir[] = {1, -1, -4, -8, -13};
93     const unsigned s = sizeof(ia) / sizeof(ia[0]);
94     int ib[s] = {0};
95     OutIter r = std::partial_sum(InIter(ia), InIter(ia+s), OutIter(ib), std::minus<int>());
96     assert(base(r) == ib + s);
97     for (unsigned i = 0; i < s; ++i)
98         assert(ib[i] == ir[i]);
99 }
100 
101 TEST_CONSTEXPR_CXX20 bool
102 test()
103 {
104     test<input_iterator<const int*>, output_iterator<int*> >();
105     test<input_iterator<const int*>, forward_iterator<int*> >();
106     test<input_iterator<const int*>, bidirectional_iterator<int*> >();
107     test<input_iterator<const int*>, random_access_iterator<int*> >();
108     test<input_iterator<const int*>, int*>();
109 
110     test<forward_iterator<const int*>, output_iterator<int*> >();
111     test<forward_iterator<const int*>, forward_iterator<int*> >();
112     test<forward_iterator<const int*>, bidirectional_iterator<int*> >();
113     test<forward_iterator<const int*>, random_access_iterator<int*> >();
114     test<forward_iterator<const int*>, int*>();
115 
116     test<bidirectional_iterator<const int*>, output_iterator<int*> >();
117     test<bidirectional_iterator<const int*>, forward_iterator<int*> >();
118     test<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
119     test<bidirectional_iterator<const int*>, random_access_iterator<int*> >();
120     test<bidirectional_iterator<const int*>, int*>();
121 
122     test<random_access_iterator<const int*>, output_iterator<int*> >();
123     test<random_access_iterator<const int*>, forward_iterator<int*> >();
124     test<random_access_iterator<const int*>, bidirectional_iterator<int*> >();
125     test<random_access_iterator<const int*>, random_access_iterator<int*> >();
126     test<random_access_iterator<const int*>, int*>();
127 
128     test<const int*, output_iterator<int*> >();
129     test<const int*, forward_iterator<int*> >();
130     test<const int*, bidirectional_iterator<int*> >();
131     test<const int*, random_access_iterator<int*> >();
132     test<const int*, int*>();
133 
134 #if TEST_STD_VER > 17
135     test_use_move();
136 #endif // TEST_STD_VER > 17
137     // C++20 can use string in constexpr evaluation, but both libc++ and MSVC
138     // don't have the support yet. In these cases omit the constexpr test.
139     // FIXME Remove constexpr string workaround introduced in D90569
140 #if TEST_STD_VER > 17 && \
141 	(!defined(__cpp_lib_constexpr_string) || __cpp_lib_constexpr_string < 201907L)
142 	if (!std::is_constant_evaluated())
143 #endif
144     test_string();
145 
146     return true;
147 }
148 
149 int main(int, char**)
150 {
151     test();
152 #if TEST_STD_VER > 17
153     static_assert(test());
154 #endif
155 
156     return 0;
157 }
158