xref: /llvm-project/libcxx/test/support/MinSequenceContainer.h (revision 0be1883c36fc19e4020fea12902481c3dd3436d2)
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 #ifndef SUPPORT_MIN_SEQUENCE_CONTAINER_H
10 #define SUPPORT_MIN_SEQUENCE_CONTAINER_H
11 
12 #include <initializer_list>
13 #include <vector>
14 
15 #include "test_iterators.h"
16 
17 template <class T, class Iterator = random_access_iterator<T*>, class ConstIterator = random_access_iterator<const T*>>
18 struct MinSequenceContainer {
19   using value_type      = T;
20   using difference_type = int;
21   using size_type       = unsigned int;
22   using iterator        = Iterator;
23   using const_iterator  = ConstIterator;
24 
25   explicit MinSequenceContainer() = default;
26   template <class It>
27   explicit MinSequenceContainer(It first, It last) : data_(first, last) {}
28   MinSequenceContainer(std::initializer_list<T> il) : data_(il) {}
29   iterator begin() { return iterator(data_.data()); }
30   const_iterator begin() const { return const_iterator(data_.data()); }
31   const_iterator cbegin() const { return const_iterator(data_.data()); }
32   iterator end() { return begin() + size(); }
33   const_iterator end() const { return begin() + size(); }
34   size_type size() const { return data_.size(); }
35   bool empty() const { return data_.empty(); }
36 
37   void clear() { data_.clear(); }
38 
39   template <class It>
40   iterator insert(const_iterator p, It first, It last) {
41     return from_vector_iterator(data_.insert(to_vector_iterator(p), first, last));
42   }
43 
44   iterator insert(const_iterator p, T value) {
45     return from_vector_iterator(data_.insert(to_vector_iterator(p), std::move(value)));
46   }
47 
48   iterator erase(const_iterator first, const_iterator last) {
49     return from_vector_iterator(data_.erase(to_vector_iterator(first), to_vector_iterator(last)));
50   }
51 
52   iterator erase(const_iterator iter) { return from_vector_iterator(data_.erase(to_vector_iterator(iter))); }
53 
54   template <class... Args>
55   iterator emplace(const_iterator pos, Args&&... args) {
56     return from_vector_iterator(data_.emplace(to_vector_iterator(pos), std::forward<Args>(args)...));
57   }
58 
59 private:
60   std::vector<T>::const_iterator to_vector_iterator(const_iterator cit) const { return cit - cbegin() + data_.begin(); }
61 
62   iterator from_vector_iterator(std::vector<T>::iterator it) { return it - data_.begin() + begin(); }
63 
64   std::vector<T> data_;
65 };
66 
67 namespace MinSequenceContainer_detail {
68 
69 // MinSequenceContainer is non-allocator-aware, because flat_set supports
70 // such (non-STL) container types, and we want to make sure they are supported.
71 template <class T>
72 concept HasAllocatorType = requires { typename T::allocator_type; };
73 static_assert(!HasAllocatorType<MinSequenceContainer<int>>);
74 
75 // MinSequenceContainer by itself doesn't support .emplace(), because we want
76 // to at least somewhat support (non-STL) container types with nothing but .insert().
77 template <class T>
78 concept HasEmplace = requires(T& t) { t.emplace(42); };
79 static_assert(!HasEmplace<MinSequenceContainer<int>>);
80 
81 } // namespace MinSequenceContainer_detail
82 
83 #endif // SUPPORT_MIN_SEQUENCE_CONTAINER_H
84