117 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// <numeric>10 11// Became constexpr in C++2012// template <InputIterator Iter, MoveConstructible T,13// Callable<auto, const T&, Iter::reference> BinaryOperation>14// requires HasAssign<T, BinaryOperation::result_type>15// && CopyConstructible<BinaryOperation>16// T17// accumulate(Iter first, Iter last, T init, BinaryOperation binary_op);18 19#include <numeric>20#include <functional>21#include <string>22#include <cassert>23 24#include "test_macros.h"25#include "test_iterators.h"26 27#if TEST_STD_VER > 1728struct rvalue_addable29{30 bool correctOperatorUsed = false;31 32 // make sure the predicate is passed an rvalue and an lvalue (so check that the first argument was moved)33 constexpr rvalue_addable operator()(rvalue_addable&& r, rvalue_addable const&) {34 r.correctOperatorUsed = true;35 return std::move(r);36 }37};38 39constexpr rvalue_addable operator+(rvalue_addable& lhs, rvalue_addable const&)40{41 lhs.correctOperatorUsed = false;42 return lhs;43}44 45constexpr rvalue_addable operator+(rvalue_addable&& lhs, rvalue_addable const&)46{47 lhs.correctOperatorUsed = true;48 return std::move(lhs);49}50 51constexpr void52test_use_move()53{54 rvalue_addable arr[100];55 auto res1 = std::accumulate(arr, arr + 100, rvalue_addable());56 auto res2 = std::accumulate(arr, arr + 100, rvalue_addable(), /*predicate=*/rvalue_addable());57 assert(res1.correctOperatorUsed);58 assert(res2.correctOperatorUsed);59}60#endif // TEST_STD_VER > 1761 62TEST_CONSTEXPR_CXX20 void test_string() {63 std::string sa[] = {"a", "b", "c"};64 assert(std::accumulate(sa, sa + 3, std::string()) == "abc");65 assert(std::accumulate(sa, sa + 3, std::string(), std::plus<std::string>()) == "abc");66}67 68template <class Iter, class T>69TEST_CONSTEXPR_CXX20 void70test(Iter first, Iter last, T init, T x)71{72 assert(std::accumulate(first, last, init, std::multiplies<T>()) == x);73}74 75template <class Iter>76TEST_CONSTEXPR_CXX20 void77test()78{79 int ia[] = {1, 2, 3, 4, 5, 6};80 unsigned sa = sizeof(ia) / sizeof(ia[0]);81 test(Iter(ia), Iter(ia), 1, 1);82 test(Iter(ia), Iter(ia), 10, 10);83 test(Iter(ia), Iter(ia+1), 1, 1);84 test(Iter(ia), Iter(ia+1), 10, 10);85 test(Iter(ia), Iter(ia+2), 1, 2);86 test(Iter(ia), Iter(ia+2), 10, 20);87 test(Iter(ia), Iter(ia+sa), 1, 720);88 test(Iter(ia), Iter(ia+sa), 10, 7200);89}90 91TEST_CONSTEXPR_CXX20 bool92test()93{94 test<cpp17_input_iterator<const int*> >();95 test<forward_iterator<const int*> >();96 test<bidirectional_iterator<const int*> >();97 test<random_access_iterator<const int*> >();98 test<const int*>();99 100#if TEST_STD_VER > 17101 test_use_move();102#endif // TEST_STD_VER > 17103 104 test_string();105 106 return true;107}108 109int main(int, char**)110{111 test();112#if TEST_STD_VER > 17113 static_assert(test());114#endif115 return 0;116}117