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 // UNSUPPORTED: gcc-9 12 13 // Became constexpr in C++20 14 // template <InputIterator Iter, MoveConstructible T, 15 // Callable<auto, const T&, Iter::reference> BinaryOperation> 16 // requires HasAssign<T, BinaryOperation::result_type> 17 // && CopyConstructible<BinaryOperation> 18 // T 19 // accumulate(Iter first, Iter last, T init, BinaryOperation binary_op); 20 21 #include <numeric> 22 #include <functional> 23 #include <string> 24 #include <cassert> 25 26 #include "test_macros.h" 27 #include "test_iterators.h" 28 29 #if TEST_STD_VER > 17 30 struct rvalue_addable 31 { 32 bool correctOperatorUsed = false; 33 34 // make sure the predicate is passed an rvalue and an lvalue (so check that the first argument was moved) 35 constexpr rvalue_addable operator()(rvalue_addable&& r, rvalue_addable const&) { 36 r.correctOperatorUsed = true; 37 return std::move(r); 38 } 39 }; 40 41 constexpr rvalue_addable operator+(rvalue_addable& lhs, rvalue_addable const&) 42 { 43 lhs.correctOperatorUsed = false; 44 return lhs; 45 } 46 47 constexpr rvalue_addable operator+(rvalue_addable&& lhs, rvalue_addable const&) 48 { 49 lhs.correctOperatorUsed = true; 50 return std::move(lhs); 51 } 52 53 constexpr void 54 test_use_move() 55 { 56 rvalue_addable arr[100]; 57 auto res1 = std::accumulate(arr, arr + 100, rvalue_addable()); 58 auto res2 = std::accumulate(arr, arr + 100, rvalue_addable(), /*predicate=*/rvalue_addable()); 59 assert(res1.correctOperatorUsed); 60 assert(res2.correctOperatorUsed); 61 } 62 #endif // TEST_STD_VER > 17 63 64 // C++20 can use string in constexpr evaluation, but both libc++ and MSVC 65 // don't have the support yet. In these cases omit the constexpr test. 66 // FIXME Remove constexpr string workaround introduced in D90569 67 #if TEST_STD_VER > 17 && \ 68 (!defined(__cpp_lib_constexpr_string) || __cpp_lib_constexpr_string < 201907L) 69 void 70 #else 71 TEST_CONSTEXPR_CXX20 void 72 #endif 73 test_string() 74 { 75 std::string sa[] = {"a", "b", "c"}; 76 assert(std::accumulate(sa, sa + 3, std::string()) == "abc"); 77 assert(std::accumulate(sa, sa + 3, std::string(), std::plus<std::string>()) == "abc"); 78 } 79 80 template <class Iter, class T> 81 TEST_CONSTEXPR_CXX20 void 82 test(Iter first, Iter last, T init, T x) 83 { 84 assert(std::accumulate(first, last, init, std::multiplies<T>()) == x); 85 } 86 87 template <class Iter> 88 TEST_CONSTEXPR_CXX20 void 89 test() 90 { 91 int ia[] = {1, 2, 3, 4, 5, 6}; 92 unsigned sa = sizeof(ia) / sizeof(ia[0]); 93 test(Iter(ia), Iter(ia), 1, 1); 94 test(Iter(ia), Iter(ia), 10, 10); 95 test(Iter(ia), Iter(ia+1), 1, 1); 96 test(Iter(ia), Iter(ia+1), 10, 10); 97 test(Iter(ia), Iter(ia+2), 1, 2); 98 test(Iter(ia), Iter(ia+2), 10, 20); 99 test(Iter(ia), Iter(ia+sa), 1, 720); 100 test(Iter(ia), Iter(ia+sa), 10, 7200); 101 } 102 103 TEST_CONSTEXPR_CXX20 bool 104 test() 105 { 106 test<cpp17_input_iterator<const int*> >(); 107 test<forward_iterator<const int*> >(); 108 test<bidirectional_iterator<const int*> >(); 109 test<random_access_iterator<const int*> >(); 110 test<const int*>(); 111 112 #if TEST_STD_VER > 17 113 test_use_move(); 114 #endif // TEST_STD_VER > 17 115 // C++20 can use string in constexpr evaluation, but both libc++ and MSVC 116 // don't have the support yet. In these cases omit the constexpr test. 117 // FIXME Remove constexpr string workaround introduced in D90569 118 #if TEST_STD_VER > 17 && \ 119 (!defined(__cpp_lib_constexpr_string) || __cpp_lib_constexpr_string < 201907L) 120 if (!std::is_constant_evaluated()) 121 #endif 122 test_string(); 123 124 return true; 125 } 126 127 int main(int, char**) 128 { 129 test(); 130 #if TEST_STD_VER > 17 131 static_assert(test()); 132 #endif 133 return 0; 134 } 135