173ebcabfSKonstantin Varlamov //===----------------------------------------------------------------------===//
273ebcabfSKonstantin Varlamov //
373ebcabfSKonstantin Varlamov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
473ebcabfSKonstantin Varlamov // See https://llvm.org/LICENSE.txt for license information.
573ebcabfSKonstantin Varlamov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
673ebcabfSKonstantin Varlamov //
773ebcabfSKonstantin Varlamov //===----------------------------------------------------------------------===//
873ebcabfSKonstantin Varlamov
973ebcabfSKonstantin Varlamov // UNSUPPORTED: c++03, c++11, c++14, c++17
1073ebcabfSKonstantin Varlamov
1173ebcabfSKonstantin Varlamov // <algorithm>
1273ebcabfSKonstantin Varlamov
1373ebcabfSKonstantin Varlamov // template<input_or_output_iterator O, copy_constructible F>
1473ebcabfSKonstantin Varlamov // requires invocable<F&> && indirectly_writable<O, invoke_result_t<F&>>
1573ebcabfSKonstantin Varlamov // constexpr O generate_n(O first, iter_difference_t<O> n, F gen); // Since C++20
1673ebcabfSKonstantin Varlamov
1773ebcabfSKonstantin Varlamov #include <algorithm>
1873ebcabfSKonstantin Varlamov #include <array>
1973ebcabfSKonstantin Varlamov #include <concepts>
2073ebcabfSKonstantin Varlamov #include <functional>
2173ebcabfSKonstantin Varlamov #include <ranges>
2273ebcabfSKonstantin Varlamov
2373ebcabfSKonstantin Varlamov #include "almost_satisfies_types.h"
2473ebcabfSKonstantin Varlamov #include "test_iterators.h"
2573ebcabfSKonstantin Varlamov
26ead7302bSKonstantin Varlamov struct IntGen {
27ead7302bSKonstantin Varlamov int operator()() const;
28ead7302bSKonstantin Varlamov };
29ead7302bSKonstantin Varlamov
30ead7302bSKonstantin Varlamov struct UncopyableGen {
31ead7302bSKonstantin Varlamov UncopyableGen(const UncopyableGen&) = delete;
32ead7302bSKonstantin Varlamov int operator()() const;
33ead7302bSKonstantin Varlamov };
34ead7302bSKonstantin Varlamov static_assert(!std::copy_constructible<UncopyableGen>);
35ead7302bSKonstantin Varlamov static_assert(std::invocable<UncopyableGen>);
36ead7302bSKonstantin Varlamov
37ead7302bSKonstantin Varlamov struct UninvocableGen {
38ead7302bSKonstantin Varlamov };
39ead7302bSKonstantin Varlamov static_assert(std::copy_constructible<UninvocableGen>);
40ead7302bSKonstantin Varlamov static_assert(!std::invocable<UninvocableGen>);
41ead7302bSKonstantin Varlamov
42ead7302bSKonstantin Varlamov struct IntPtrGen {
43ead7302bSKonstantin Varlamov int* operator()() const;
44ead7302bSKonstantin Varlamov };
45ead7302bSKonstantin Varlamov
46ead7302bSKonstantin Varlamov // Test type constraints.
47ead7302bSKonstantin Varlamov // ======================================================
48ead7302bSKonstantin Varlamov
49ead7302bSKonstantin Varlamov template <class Iter = int*, class Gen = IntGen>
50ead7302bSKonstantin Varlamov concept HasGenerateNIter =
51ead7302bSKonstantin Varlamov requires(Iter&& iter, Gen&& gen) {
52ead7302bSKonstantin Varlamov std::ranges::generate_n(std::forward<Iter>(iter), 0, std::forward<Gen>(gen));
53ead7302bSKonstantin Varlamov };
54ead7302bSKonstantin Varlamov
55ead7302bSKonstantin Varlamov static_assert(HasGenerateNIter<int*, IntGen>);
56ead7302bSKonstantin Varlamov
57ead7302bSKonstantin Varlamov // !input_or_output_iterator<O>
58ead7302bSKonstantin Varlamov static_assert(!HasGenerateNIter<InputIteratorNotInputOrOutputIterator>);
59ead7302bSKonstantin Varlamov
60ead7302bSKonstantin Varlamov // !copy_constructible<F>
61ead7302bSKonstantin Varlamov static_assert(!HasGenerateNIter<int*, UncopyableGen>);
62ead7302bSKonstantin Varlamov
63ead7302bSKonstantin Varlamov // !invocable<F&>
64ead7302bSKonstantin Varlamov static_assert(!HasGenerateNIter<int*, UninvocableGen>);
65ead7302bSKonstantin Varlamov
66ead7302bSKonstantin Varlamov // !indirectly_writable<O, invoke_result_t<F&>>
67ead7302bSKonstantin Varlamov static_assert(!HasGenerateNIter<int*, IntPtrGen>);
68ead7302bSKonstantin Varlamov
69*fb855eb9SMark de Wever template <class Iter, std::size_t N, class Gen>
test_one(std::array<int,N> in,std::size_t n,Gen gen,std::array<int,N> expected)70*fb855eb9SMark de Wever constexpr void test_one(std::array<int, N> in, std::size_t n, Gen gen, std::array<int, N> expected) {
71ead7302bSKonstantin Varlamov assert(n <= N);
72ead7302bSKonstantin Varlamov
73ead7302bSKonstantin Varlamov auto begin = Iter(in.data());
74ead7302bSKonstantin Varlamov
75ead7302bSKonstantin Varlamov std::same_as<Iter> decltype(auto) result = std::ranges::generate_n(std::move(begin), n, gen);
76ead7302bSKonstantin Varlamov assert(base(result) == in.data() + n);
77ead7302bSKonstantin Varlamov assert(in == expected);
78ead7302bSKonstantin Varlamov }
79ead7302bSKonstantin Varlamov
80ead7302bSKonstantin Varlamov template <class Iter>
test_iter()81ead7302bSKonstantin Varlamov constexpr void test_iter() {
82ead7302bSKonstantin Varlamov auto gen = [ctr = 1] () mutable { return ctr++; };
83ead7302bSKonstantin Varlamov
84ead7302bSKonstantin Varlamov // Empty sequence.
85ead7302bSKonstantin Varlamov test_one<Iter, 0>({}, 0, gen, {});
86ead7302bSKonstantin Varlamov // 1-element sequence, n = 0.
87ead7302bSKonstantin Varlamov test_one<Iter>(std::array{-10}, 0, gen, {-10});
88ead7302bSKonstantin Varlamov // 1-element sequence, n = 1.
89ead7302bSKonstantin Varlamov test_one<Iter>(std::array{-10}, 1, gen, {1});
90ead7302bSKonstantin Varlamov // Longer sequence, n = 3.
91ead7302bSKonstantin Varlamov test_one<Iter>(std::array{-10, -20, -30, -40, -50}, 3, gen, {1, 2, 3, -40, -50});
92ead7302bSKonstantin Varlamov // Longer sequence, n = 5.
93ead7302bSKonstantin Varlamov test_one<Iter>(std::array<int, 5>{}, 5, gen, {1, 2, 3, 4, 5});
94ead7302bSKonstantin Varlamov }
95ead7302bSKonstantin Varlamov
test_iterators()96ead7302bSKonstantin Varlamov constexpr void test_iterators() {
97ead7302bSKonstantin Varlamov test_iter<cpp17_input_iterator<int*>>();
98ead7302bSKonstantin Varlamov test_iter<cpp20_input_iterator<int*>>();
99ead7302bSKonstantin Varlamov test_iter<cpp17_output_iterator<int*>>();
100ead7302bSKonstantin Varlamov test_iter<cpp20_output_iterator<int*>>();
101ead7302bSKonstantin Varlamov test_iter<forward_iterator<int*>>();
102ead7302bSKonstantin Varlamov test_iter<bidirectional_iterator<int*>>();
103ead7302bSKonstantin Varlamov test_iter<random_access_iterator<int*>>();
104ead7302bSKonstantin Varlamov test_iter<contiguous_iterator<int*>>();
105ead7302bSKonstantin Varlamov test_iter<int*>();
106ead7302bSKonstantin Varlamov }
10773ebcabfSKonstantin Varlamov
test()10873ebcabfSKonstantin Varlamov constexpr bool test() {
109ead7302bSKonstantin Varlamov test_iterators();
110ead7302bSKonstantin Varlamov
111ead7302bSKonstantin Varlamov { // Complexity: exactly N evaluations of `gen()` and assignments.
112ead7302bSKonstantin Varlamov struct AssignedOnce {
113ead7302bSKonstantin Varlamov bool assigned = false;
114ead7302bSKonstantin Varlamov constexpr AssignedOnce& operator=(const AssignedOnce&) {
115ead7302bSKonstantin Varlamov assert(!assigned);
116ead7302bSKonstantin Varlamov assigned = true;
117ead7302bSKonstantin Varlamov return *this;
118ead7302bSKonstantin Varlamov }
119ead7302bSKonstantin Varlamov };
120ead7302bSKonstantin Varlamov
121ead7302bSKonstantin Varlamov int gen_invocations = 0;
122ead7302bSKonstantin Varlamov auto gen = [&gen_invocations] { ++gen_invocations; return AssignedOnce(); };
123*fb855eb9SMark de Wever constexpr std::size_t N1 = 10;
124*fb855eb9SMark de Wever constexpr std::size_t N2 = N1 / 2;
125ead7302bSKonstantin Varlamov std::array<AssignedOnce, N1> in;
126ead7302bSKonstantin Varlamov
127ead7302bSKonstantin Varlamov auto result = std::ranges::generate_n(in.begin(), N2, gen);
128ead7302bSKonstantin Varlamov assert(std::ranges::all_of(std::ranges::subrange(in.begin(), result), &AssignedOnce::assigned));
129ead7302bSKonstantin Varlamov assert(std::ranges::none_of(std::ranges::subrange(result, in.end()), &AssignedOnce::assigned));
130ead7302bSKonstantin Varlamov assert(gen_invocations == N2);
131ead7302bSKonstantin Varlamov }
132ead7302bSKonstantin Varlamov
13373ebcabfSKonstantin Varlamov
13473ebcabfSKonstantin Varlamov return true;
13573ebcabfSKonstantin Varlamov }
13673ebcabfSKonstantin Varlamov
main(int,char **)13773ebcabfSKonstantin Varlamov int main(int, char**) {
13873ebcabfSKonstantin Varlamov test();
13973ebcabfSKonstantin Varlamov static_assert(test());
14073ebcabfSKonstantin Varlamov
14173ebcabfSKonstantin Varlamov return 0;
14273ebcabfSKonstantin Varlamov }
143