[RISCV] Fix mgather -> riscv.masked.strided.load combine not extending indices (...
[llvm-project.git] / libcxx / test / std / containers / sequences / from_range_sequence_containers.h
blob859b9c535f7ba3714f4abdd5f2f3b418dd86ede6
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 //===----------------------------------------------------------------------===//
9 #ifndef SUPPORT_FROM_RANGE_SEQUENCE_CONTAINERS_H
10 #define SUPPORT_FROM_RANGE_SEQUENCE_CONTAINERS_H
12 #include <algorithm>
13 #include <array>
14 #include <cassert>
15 #include <cstddef>
16 #include <iterator>
17 #include <ranges>
18 #include <utility>
20 #include "../exception_safety_helpers.h"
21 #include "../from_range_helpers.h"
22 #include "MoveOnly.h"
23 #include "almost_satisfies_types.h"
24 #include "count_new.h"
25 #include "test_iterators.h"
26 #include "test_macros.h"
28 template <class T>
29 concept HasSize = requires (const T& value) { value.size(); };
31 template <class Container, class Range>
32 concept HasFromRangeCtr = requires (Range&& range) {
33 Container(std::from_range, std::forward<Range>(range));
34 Container(std::from_range, std::forward<Range>(range), std::allocator<typename Container::value_type>());
37 template <template <class...> class Container, class T, class U>
38 constexpr bool test_constraints() {
39 // Input range with the same value type.
40 static_assert(HasFromRangeCtr<Container<T>, InputRange<T>>);
41 // Input range with a convertible value type.
42 static_assert(HasFromRangeCtr<Container<T>, InputRange<U>>);
43 // Input range with a non-convertible value type.
44 static_assert(!HasFromRangeCtr<Container<T>, InputRange<Empty>>);
45 // Not an input range.
46 static_assert(!HasFromRangeCtr<Container<T>, InputRangeNotDerivedFrom>);
47 static_assert(!HasFromRangeCtr<Container<T>, InputRangeNotIndirectlyReadable>);
48 static_assert(!HasFromRangeCtr<Container<T>, InputRangeNotInputOrOutputIterator>);
50 // Note: there are no constraints on the allocator (it's not a separate template type of the constructor)`.
52 return true;
55 // Note: `std::array` is used to avoid dealing with `vector<bool>`.
56 template <template <class ...> class Container,
57 class T,
58 class Iter,
59 class Sent,
60 class Alloc,
61 std::size_t N,
62 class ValidateFunc>
63 constexpr void test_sequence_container_with_input(std::array<T, N>&& input, ValidateFunc validate) {
64 auto in = wrap_input<Iter, Sent>(input);
66 { // (range)
67 Container<T> c(std::from_range, in);
69 if constexpr (HasSize<Container<T>>) {
70 assert(c.size() == static_cast<std::size_t>(std::distance(c.begin(), c.end())));
72 assert(std::ranges::equal(in, c));
73 validate(c);
76 { // (range, allocator)
77 Alloc alloc;
78 Container<T, Alloc> c(std::from_range, in, alloc);
80 assert(c.get_allocator() == alloc);
81 if constexpr (HasSize<Container<T, Alloc>>) {
82 assert(c.size() == static_cast<std::size_t>(std::distance(c.begin(), c.end())));
84 assert(std::ranges::equal(in, c));
85 validate(c);
89 template <template <class ...> class Container,
90 class T,
91 class Iter,
92 class Sent,
93 class Alloc,
94 class ValidateFunc>
95 constexpr void test_sequence_container(ValidateFunc validate) {
96 // Normal input.
97 test_sequence_container_with_input<Container, T, Iter, Sent, Alloc>(std::array{0, 5, 12, 7, -1, 8, 26}, validate);
98 // Empty input.
99 test_sequence_container_with_input<Container, T, Iter, Sent, Alloc>(std::array<int, 0>{}, validate);
100 // Single-element input.
101 test_sequence_container_with_input<Container, T, Iter, Sent, Alloc>(std::array{5}, validate);
104 template <template <class ...> class Container>
105 constexpr void test_sequence_container_move_only() {
106 MoveOnly input[5];
107 std::ranges::subrange in(std::move_iterator{input}, std::move_iterator{input + 5});
109 [[maybe_unused]] Container<MoveOnly> c(std::from_range, in);
112 template <class Iter,
113 class Sent,
114 class Alloc,
115 class ValidateFunc>
116 constexpr void test_vector_bool(ValidateFunc validate) {
117 // Normal input.
118 test_sequence_container_with_input<std::vector, bool, Iter, Sent, Alloc>(
119 std::array{true, false, false, true, false, true, true, true, false, true}, validate);
120 // Empty input.
121 test_sequence_container_with_input<std::vector, bool, Iter, Sent, Alloc>(std::array<bool, 0>{}, validate);
122 // Single-element input.
123 test_sequence_container_with_input<std::vector, bool, Iter, Sent, Alloc>(std::array{true}, validate);
126 template <template <class ...> class Container>
127 void test_exception_safety_throwing_copy() {
128 #if !defined(TEST_HAS_NO_EXCEPTIONS)
129 constexpr int ThrowOn = 3;
130 using T = ThrowingCopy<ThrowOn>;
131 test_exception_safety_throwing_copy<ThrowOn, /*Size=*/5>([](T* from, T* to) {
132 [[maybe_unused]] Container<T> c(std::from_range, std::ranges::subrange(from, to));
134 #endif
137 template <template <class ...> class Container, class T>
138 void test_exception_safety_throwing_allocator() {
139 #if !defined(TEST_HAS_NO_EXCEPTIONS)
140 T in[] = {0, 1};
142 try {
143 ThrowingAllocator<T> alloc;
145 globalMemCounter.reset();
146 Container<T, ThrowingAllocator<T>> c(std::from_range, in, alloc);
147 assert(false); // The constructor call above should throw.
149 } catch (int) {
150 assert(globalMemCounter.new_called == globalMemCounter.delete_called);
152 #endif
155 #endif // SUPPORT_FROM_RANGE_SEQUENCE_CONTAINERS_H