xref: /llvm-project/libcxx/test/std/containers/from_range_helpers.h (revision f1db578f0d0f9d83f8b8b88d92ad5397377a74b2)
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