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 | // <algorithm> |
10 | |
11 | // UNSUPPORTED: c++03, c++11, c++14, c++17 |
12 | |
13 | // template<class T, output_iterator<const T&> O> |
14 | // constexpr O ranges::fill_n(O first, iter_difference_t<O> n, const T& value); |
15 | |
16 | #include <algorithm> |
17 | #include <array> |
18 | #include <cassert> |
19 | #include <ranges> |
20 | #include <string> |
21 | |
22 | #include "almost_satisfies_types.h" |
23 | #include "test_iterators.h" |
24 | |
25 | template <class Iter> |
26 | concept HasFillN = requires(Iter iter) { std::ranges::fill_n(iter, int{}, int{}); }; |
27 | |
28 | struct WrongType {}; |
29 | |
30 | static_assert(HasFillN<int*>); |
31 | static_assert(!HasFillN<WrongType*>); |
32 | static_assert(!HasFillN<OutputIteratorNotIndirectlyWritable>); |
33 | static_assert(!HasFillN<OutputIteratorNotInputOrOutputIterator>); |
34 | |
35 | template <class It, class Sent = It> |
36 | constexpr void test_iterators() { |
37 | { // simple test |
38 | int a[3]; |
39 | std::same_as<It> decltype(auto) ret = std::ranges::fill_n(It(a), 3, 1); |
40 | assert(std::all_of(a, a + 3, [](int i) { return i == 1; })); |
41 | assert(base(ret) == a + 3); |
42 | } |
43 | |
44 | { // check that an empty range works |
45 | std::array<int, 0> a; |
46 | auto ret = std::ranges::fill_n(It(a.data()), 0, 1); |
47 | assert(base(ret) == a.data()); |
48 | } |
49 | } |
50 | |
51 | constexpr bool test() { |
52 | test_iterators<cpp17_output_iterator<int*>, sentinel_wrapper<cpp17_output_iterator<int*>>>(); |
53 | test_iterators<cpp20_output_iterator<int*>, sentinel_wrapper<cpp20_output_iterator<int*>>>(); |
54 | test_iterators<forward_iterator<int*>>(); |
55 | test_iterators<bidirectional_iterator<int*>>(); |
56 | test_iterators<random_access_iterator<int*>>(); |
57 | test_iterators<contiguous_iterator<int*>>(); |
58 | test_iterators<int*>(); |
59 | |
60 | { // check that every element is copied once |
61 | struct S { |
62 | bool copied = false; |
63 | constexpr S& operator=(const S&) { |
64 | assert(!copied); |
65 | copied = true; |
66 | return *this; |
67 | } |
68 | }; |
69 | |
70 | S a[5]; |
71 | std::ranges::fill_n(a, 5, S {}); |
72 | assert(std::all_of(a, a + 5, [](S& s) { return s.copied; })); |
73 | } |
74 | |
75 | { // check that non-trivially copyable items are copied properly |
76 | std::array<std::string, 10> a; |
77 | auto ret = std::ranges::fill_n(a.data(), 10, "long long string so no SSO" ); |
78 | assert(ret == a.data() + a.size()); |
79 | assert(std::all_of(a.begin(), a.end(), [](auto& s) { return s == "long long string so no SSO" ; })); |
80 | } |
81 | |
82 | return true; |
83 | } |
84 | |
85 | int main(int, char**) { |
86 | test(); |
87 | static_assert(test()); |
88 | |
89 | return 0; |
90 | } |
91 | |