117bbb224Svarconst //===----------------------------------------------------------------------===//
217bbb224Svarconst //
317bbb224Svarconst // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
417bbb224Svarconst // See https://llvm.org/LICENSE.txt for license information.
517bbb224Svarconst // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
617bbb224Svarconst //
717bbb224Svarconst //===----------------------------------------------------------------------===//
817bbb224Svarconst
917bbb224Svarconst #ifndef SUPPORT_FROM_RANGE_HELPERS_H
1017bbb224Svarconst #define SUPPORT_FROM_RANGE_HELPERS_H
1117bbb224Svarconst
12*f1db578fSStephan T. Lavavej #include <array>
1317bbb224Svarconst #include <cstddef>
1417bbb224Svarconst #include <iterator>
1517bbb224Svarconst #include <type_traits>
16*f1db578fSStephan T. Lavavej #include <vector>
1717bbb224Svarconst
1817bbb224Svarconst #include "min_allocator.h"
1917bbb224Svarconst #include "test_allocator.h"
2017bbb224Svarconst #include "test_iterators.h"
2117bbb224Svarconst #include "test_macros.h"
2217bbb224Svarconst #include "type_algorithms.h"
2317bbb224Svarconst
2417bbb224Svarconst struct Empty {};
2517bbb224Svarconst
2617bbb224Svarconst template <class T>
2717bbb224Svarconst struct InputRange {
2817bbb224Svarconst cpp20_input_iterator<T*> begin();
2917bbb224Svarconst sentinel_wrapper<cpp20_input_iterator<T*>> end();
3017bbb224Svarconst };
3117bbb224Svarconst
3217bbb224Svarconst template <class Iter, class Sent, std::ranges::input_range Range>
wrap_input(Range && input)3317bbb224Svarconst constexpr auto wrap_input(Range&& input) {
3417bbb224Svarconst auto b = Iter(std::ranges::begin(input));
3517bbb224Svarconst auto e = Sent(Iter(std::ranges::end(input)));
3617bbb224Svarconst return std::ranges::subrange(std::move(b), std::move(e));
3717bbb224Svarconst }
3817bbb224Svarconst
39*f1db578fSStephan T. Lavavej template <class Iter, class Sent, class T, std::size_t N>
wrap_input(std::array<T,N> & input)40*f1db578fSStephan T. Lavavej constexpr auto wrap_input(std::array<T, N>& input) {
41*f1db578fSStephan T. Lavavej auto b = Iter(input.data());
42*f1db578fSStephan T. Lavavej auto e = Sent(Iter(input.data() + input.size()));
43*f1db578fSStephan T. Lavavej return std::ranges::subrange(std::move(b), std::move(e));
44*f1db578fSStephan T. Lavavej }
45*f1db578fSStephan T. Lavavej
4617bbb224Svarconst template <class Iter, class Sent, class T>
wrap_input(std::vector<T> & input)4717bbb224Svarconst constexpr auto wrap_input(std::vector<T>& input) {
4817bbb224Svarconst auto b = Iter(input.data());
4917bbb224Svarconst auto e = Sent(Iter(input.data() + input.size()));
5017bbb224Svarconst return std::ranges::subrange(std::move(b), std::move(e));
5117bbb224Svarconst }
5217bbb224Svarconst
5317bbb224Svarconst struct KeyValue {
5417bbb224Svarconst int key; // Only the key is considered for equality comparison.
5517bbb224Svarconst char value; // Allows distinguishing equivalent instances.
5617bbb224Svarconst
5717bbb224Svarconst bool operator<(const KeyValue& other) const { return key < other.key; }
5817bbb224Svarconst bool operator==(const KeyValue& other) const { return key == other.key; }
5917bbb224Svarconst };
6017bbb224Svarconst
6117bbb224Svarconst template <>
6217bbb224Svarconst struct std::hash<KeyValue> {
6317bbb224Svarconst std::size_t operator()(const KeyValue& kv) const {
6417bbb224Svarconst return kv.key;
6517bbb224Svarconst }
6617bbb224Svarconst };
6717bbb224Svarconst
6817bbb224Svarconst #if !defined(TEST_HAS_NO_EXCEPTIONS)
6917bbb224Svarconst
7017bbb224Svarconst template <class T>
7117bbb224Svarconst struct ThrowingAllocator {
7217bbb224Svarconst using value_type = T;
7317bbb224Svarconst using char_type = T;
7417bbb224Svarconst using is_always_equal = std::false_type;
7517bbb224Svarconst
7617bbb224Svarconst ThrowingAllocator() = default;
7717bbb224Svarconst
7817bbb224Svarconst template <class U>
7917bbb224Svarconst ThrowingAllocator(const ThrowingAllocator<U>&) {}
8017bbb224Svarconst
8117bbb224Svarconst T* allocate(std::size_t) { throw 1; }
8217bbb224Svarconst void deallocate(T*, std::size_t) {}
8317bbb224Svarconst
8417bbb224Svarconst template <class U>
8517bbb224Svarconst friend bool operator==(const ThrowingAllocator&, const ThrowingAllocator<U>&) {
8617bbb224Svarconst return true;
8717bbb224Svarconst }
8817bbb224Svarconst };
8917bbb224Svarconst #endif
9017bbb224Svarconst
9117bbb224Svarconst template <class T, class Func>
9217bbb224Svarconst constexpr void for_all_iterators_and_allocators(Func f) {
9317bbb224Svarconst using Iterators = types::type_list<
9417bbb224Svarconst cpp20_input_iterator<T*>,
9517bbb224Svarconst forward_iterator<T*>,
9617bbb224Svarconst bidirectional_iterator<T*>,
9717bbb224Svarconst random_access_iterator<T*>,
9817bbb224Svarconst contiguous_iterator<T*>,
9917bbb224Svarconst T*
10017bbb224Svarconst >;
10117bbb224Svarconst
10217bbb224Svarconst types::for_each(Iterators{}, [=]<class Iter>() {
10317bbb224Svarconst f.template operator()<Iter, sentinel_wrapper<Iter>, std::allocator<T>>();
10417bbb224Svarconst f.template operator()<Iter, sentinel_wrapper<Iter>, test_allocator<T>>();
10517bbb224Svarconst f.template operator()<Iter, sentinel_wrapper<Iter>, min_allocator<T>>();
10617bbb224Svarconst f.template operator()<Iter, sentinel_wrapper<Iter>, safe_allocator<T>>();
10717bbb224Svarconst
10817bbb224Svarconst if constexpr (std::sentinel_for<Iter, Iter>) {
10917bbb224Svarconst f.template operator()<Iter, Iter, std::allocator<T>>();
11017bbb224Svarconst f.template operator()<Iter, Iter, test_allocator<T>>();
11117bbb224Svarconst f.template operator()<Iter, Iter, min_allocator<T>>();
11217bbb224Svarconst f.template operator()<Iter, Iter, safe_allocator<T>>();
11317bbb224Svarconst }
11417bbb224Svarconst });
11517bbb224Svarconst }
11617bbb224Svarconst
11717bbb224Svarconst #endif // SUPPORT_FROM_RANGE_HELPERS_H
118